packet.c revision 162852
1162852Sdes/* $OpenBSD: packet.c,v 1.145 2006/09/19 21:14:08 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_systm.h> 51162852Sdes#include <netinet/in.h> 52162852Sdes#include <netinet/ip.h> 53162852Sdes#include <arpa/inet.h> 54162852Sdes 55162852Sdes#include <errno.h> 56162852Sdes#include <stdarg.h> 57162852Sdes#include <stdio.h> 58162852Sdes#include <stdlib.h> 59162852Sdes#include <string.h> 60162852Sdes#include <unistd.h> 61162852Sdes#include <signal.h> 62162852Sdes 6357429Smarkm#include "xmalloc.h" 6457429Smarkm#include "buffer.h" 6557429Smarkm#include "packet.h" 6657429Smarkm#include "crc32.h" 6757429Smarkm#include "compress.h" 6857429Smarkm#include "deattack.h" 6960573Skris#include "channels.h" 7060573Skris#include "compat.h" 7176259Sgreen#include "ssh1.h" 7260573Skris#include "ssh2.h" 7369587Sgreen#include "cipher.h" 74162852Sdes#include "key.h" 7560573Skris#include "kex.h" 7676259Sgreen#include "mac.h" 7776259Sgreen#include "log.h" 7876259Sgreen#include "canohost.h" 7992555Sdes#include "misc.h" 8098675Sdes#include "ssh.h" 8160573Skris 8260573Skris#ifdef PACKET_DEBUG 8360573Skris#define DBG(x) x 8460573Skris#else 8560573Skris#define DBG(x) 8660573Skris#endif 8760573Skris 8857429Smarkm/* 8957429Smarkm * This variable contains the file descriptors used for communicating with 9057429Smarkm * the other side. connection_in is used for reading; connection_out for 9157429Smarkm * writing. These can be the same descriptor, in which case it is assumed to 9257429Smarkm * be a socket. 9357429Smarkm */ 9457429Smarkmstatic int connection_in = -1; 9557429Smarkmstatic int connection_out = -1; 9657429Smarkm 9757429Smarkm/* Protocol flags for the remote side. */ 9876259Sgreenstatic u_int remote_protocol_flags = 0; 9957429Smarkm 10057429Smarkm/* Encryption context for receiving data. This is only used for decryption. */ 10157429Smarkmstatic CipherContext receive_context; 10257429Smarkm 10357429Smarkm/* Encryption context for sending data. This is only used for encryption. */ 10457429Smarkmstatic CipherContext send_context; 10557429Smarkm 10657429Smarkm/* Buffer for raw input data from the socket. */ 10798675SdesBuffer input; 10857429Smarkm 10957429Smarkm/* Buffer for raw output data going to the socket. */ 11098675SdesBuffer output; 11157429Smarkm 11257429Smarkm/* Buffer for the partial outgoing packet being constructed. */ 11357429Smarkmstatic Buffer outgoing_packet; 11457429Smarkm 11557429Smarkm/* Buffer for the incoming packet currently being processed. */ 11657429Smarkmstatic Buffer incoming_packet; 11757429Smarkm 11857429Smarkm/* Scratch buffer for packet compression/decompression. */ 11957429Smarkmstatic Buffer compression_buffer; 12076259Sgreenstatic int compression_buffer_ready = 0; 12157429Smarkm 12257429Smarkm/* Flag indicating whether packet compression/decompression is enabled. */ 12357429Smarkmstatic int packet_compression = 0; 12457429Smarkm 12557429Smarkm/* default maximum packet size */ 126124208Sdesu_int max_packet_size = 32768; 12757429Smarkm 12857429Smarkm/* Flag indicating whether this module has been initialized. */ 12957429Smarkmstatic int initialized = 0; 13057429Smarkm 13157429Smarkm/* Set to true if the connection is interactive. */ 13257429Smarkmstatic int interactive_mode = 0; 13357429Smarkm 134149749Sdes/* Set to true if we are the server side. */ 135149749Sdesstatic int server_side = 0; 136149749Sdes 137149749Sdes/* Set to true if we are authenticated. */ 138149749Sdesstatic int after_authentication = 0; 139149749Sdes 14060573Skris/* Session key information for Encryption and MAC */ 14176259SgreenNewkeys *newkeys[MODE_MAX]; 142124208Sdesstatic struct packet_state { 143124208Sdes u_int32_t seqnr; 144124208Sdes u_int32_t packets; 145124208Sdes u_int64_t blocks; 146124208Sdes} p_read, p_send; 14760573Skris 148124208Sdesstatic u_int64_t max_blocks_in, max_blocks_out; 149124208Sdesstatic u_int32_t rekey_limit; 150124208Sdes 15198675Sdes/* Session key for protocol v1 */ 15298675Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 15398675Sdesstatic u_int ssh1_keylen; 15498675Sdes 15592555Sdes/* roundup current message to extra_pad bytes */ 15692555Sdesstatic u_char extra_pad = 0; 15760573Skris 158124208Sdesstruct packet { 159124208Sdes TAILQ_ENTRY(packet) next; 160124208Sdes u_char type; 161124208Sdes Buffer payload; 162124208Sdes}; 163124208SdesTAILQ_HEAD(, packet) outgoing; 164124208Sdes 16557429Smarkm/* 16657429Smarkm * Sets the descriptors used for communication. Disables encryption until 16757429Smarkm * packet_set_encryption_key is called. 16857429Smarkm */ 16957429Smarkmvoid 17057429Smarkmpacket_set_connection(int fd_in, int fd_out) 17157429Smarkm{ 17269587Sgreen Cipher *none = cipher_by_name("none"); 173106121Sdes 17469587Sgreen if (none == NULL) 17569587Sgreen fatal("packet_set_connection: cannot load cipher 'none'"); 17657429Smarkm connection_in = fd_in; 17757429Smarkm connection_out = fd_out; 178137015Sdes cipher_init(&send_context, none, (const u_char *)"", 179137015Sdes 0, NULL, 0, CIPHER_ENCRYPT); 180137015Sdes cipher_init(&receive_context, none, (const u_char *)"", 181137015Sdes 0, NULL, 0, CIPHER_DECRYPT); 18292555Sdes newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; 18357429Smarkm if (!initialized) { 18457429Smarkm initialized = 1; 18557429Smarkm buffer_init(&input); 18657429Smarkm buffer_init(&output); 18757429Smarkm buffer_init(&outgoing_packet); 18857429Smarkm buffer_init(&incoming_packet); 189124208Sdes TAILQ_INIT(&outgoing); 19057429Smarkm } 19157429Smarkm} 19257429Smarkm 19357429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */ 19457429Smarkm 19557429Smarkmint 19692555Sdespacket_connection_is_on_socket(void) 19757429Smarkm{ 19857429Smarkm struct sockaddr_storage from, to; 19957429Smarkm socklen_t fromlen, tolen; 20057429Smarkm 20157429Smarkm /* filedescriptors in and out are the same, so it's a socket */ 20257429Smarkm if (connection_in == connection_out) 20357429Smarkm return 1; 20457429Smarkm fromlen = sizeof(from); 20557429Smarkm memset(&from, 0, sizeof(from)); 20657429Smarkm if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0) 20757429Smarkm return 0; 20857429Smarkm tolen = sizeof(to); 20957429Smarkm memset(&to, 0, sizeof(to)); 21057429Smarkm if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0) 21157429Smarkm return 0; 21257429Smarkm if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) 21357429Smarkm return 0; 21457429Smarkm if (from.ss_family != AF_INET && from.ss_family != AF_INET6) 21557429Smarkm return 0; 21657429Smarkm return 1; 21757429Smarkm} 21857429Smarkm 21998675Sdes/* 22098675Sdes * Exports an IV from the CipherContext required to export the key 22198675Sdes * state back from the unprivileged child to the privileged parent 22298675Sdes * process. 22398675Sdes */ 22498675Sdes 22598675Sdesvoid 22698675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len) 22798675Sdes{ 22898675Sdes CipherContext *cc; 22998675Sdes 23098675Sdes if (mode == MODE_OUT) 23198675Sdes cc = &send_context; 23298675Sdes else 23398675Sdes cc = &receive_context; 23498675Sdes 23598675Sdes cipher_get_keyiv(cc, iv, len); 23698675Sdes} 23798675Sdes 23898675Sdesint 23998675Sdespacket_get_keycontext(int mode, u_char *dat) 24098675Sdes{ 24198675Sdes CipherContext *cc; 24298675Sdes 24398675Sdes if (mode == MODE_OUT) 24498675Sdes cc = &send_context; 24598675Sdes else 24698675Sdes cc = &receive_context; 24798675Sdes 24898675Sdes return (cipher_get_keycontext(cc, dat)); 24998675Sdes} 25098675Sdes 25198675Sdesvoid 25298675Sdespacket_set_keycontext(int mode, u_char *dat) 25398675Sdes{ 25498675Sdes CipherContext *cc; 25598675Sdes 25698675Sdes if (mode == MODE_OUT) 25798675Sdes cc = &send_context; 25898675Sdes else 25998675Sdes cc = &receive_context; 26098675Sdes 26198675Sdes cipher_set_keycontext(cc, dat); 26298675Sdes} 26398675Sdes 26498675Sdesint 26598675Sdespacket_get_keyiv_len(int mode) 26698675Sdes{ 26798675Sdes CipherContext *cc; 26898675Sdes 26998675Sdes if (mode == MODE_OUT) 27098675Sdes cc = &send_context; 27198675Sdes else 27298675Sdes cc = &receive_context; 27398675Sdes 27498675Sdes return (cipher_get_keyiv_len(cc)); 27598675Sdes} 276162852Sdes 27798675Sdesvoid 27898675Sdespacket_set_iv(int mode, u_char *dat) 27998675Sdes{ 28098675Sdes CipherContext *cc; 28198675Sdes 28298675Sdes if (mode == MODE_OUT) 28398675Sdes cc = &send_context; 28498675Sdes else 28598675Sdes cc = &receive_context; 28698675Sdes 28798675Sdes cipher_set_keyiv(cc, dat); 28898675Sdes} 289162852Sdes 29098675Sdesint 291124208Sdespacket_get_ssh1_cipher(void) 29298675Sdes{ 29398675Sdes return (cipher_get_number(receive_context.cipher)); 29498675Sdes} 29598675Sdes 296124208Sdesvoid 297124208Sdespacket_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets) 298124208Sdes{ 299124208Sdes struct packet_state *state; 30098675Sdes 301124208Sdes state = (mode == MODE_IN) ? &p_read : &p_send; 302124208Sdes *seqnr = state->seqnr; 303124208Sdes *blocks = state->blocks; 304124208Sdes *packets = state->packets; 30598675Sdes} 30698675Sdes 30798675Sdesvoid 308124208Sdespacket_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets) 30998675Sdes{ 310124208Sdes struct packet_state *state; 311124208Sdes 312124208Sdes state = (mode == MODE_IN) ? &p_read : &p_send; 313124208Sdes state->seqnr = seqnr; 314124208Sdes state->blocks = blocks; 315124208Sdes state->packets = packets; 31698675Sdes} 31798675Sdes 31857429Smarkm/* returns 1 if connection is via ipv4 */ 31957429Smarkm 32057429Smarkmint 32192555Sdespacket_connection_is_ipv4(void) 32257429Smarkm{ 32357429Smarkm struct sockaddr_storage to; 32457429Smarkm socklen_t tolen = sizeof(to); 32557429Smarkm 32657429Smarkm memset(&to, 0, sizeof(to)); 32757429Smarkm if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) 32857429Smarkm return 0; 32998937Sdes if (to.ss_family == AF_INET) 33098937Sdes return 1; 33198937Sdes#ifdef IPV4_IN_IPV6 332126274Sdes if (to.ss_family == AF_INET6 && 33398937Sdes IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) 33498937Sdes return 1; 33598937Sdes#endif 33698937Sdes return 0; 33757429Smarkm} 33857429Smarkm 33957429Smarkm/* Sets the connection into non-blocking mode. */ 34057429Smarkm 34157429Smarkmvoid 34292555Sdespacket_set_nonblocking(void) 34357429Smarkm{ 34457429Smarkm /* Set the socket into non-blocking mode. */ 345137015Sdes set_nonblock(connection_in); 34657429Smarkm 347137015Sdes if (connection_out != connection_in) 348137015Sdes set_nonblock(connection_out); 34957429Smarkm} 35057429Smarkm 35157429Smarkm/* Returns the socket used for reading. */ 35257429Smarkm 35357429Smarkmint 35492555Sdespacket_get_connection_in(void) 35557429Smarkm{ 35657429Smarkm return connection_in; 35757429Smarkm} 35857429Smarkm 35957429Smarkm/* Returns the descriptor used for writing. */ 36057429Smarkm 36157429Smarkmint 36292555Sdespacket_get_connection_out(void) 36357429Smarkm{ 36457429Smarkm return connection_out; 36557429Smarkm} 36657429Smarkm 36757429Smarkm/* Closes the connection and clears and frees internal data structures. */ 36857429Smarkm 36957429Smarkmvoid 37092555Sdespacket_close(void) 37157429Smarkm{ 37257429Smarkm if (!initialized) 37357429Smarkm return; 37457429Smarkm initialized = 0; 37557429Smarkm if (connection_in == connection_out) { 37657429Smarkm shutdown(connection_out, SHUT_RDWR); 37757429Smarkm close(connection_out); 37857429Smarkm } else { 37957429Smarkm close(connection_in); 38057429Smarkm close(connection_out); 38157429Smarkm } 38257429Smarkm buffer_free(&input); 38357429Smarkm buffer_free(&output); 38457429Smarkm buffer_free(&outgoing_packet); 38557429Smarkm buffer_free(&incoming_packet); 38676259Sgreen if (compression_buffer_ready) { 38757429Smarkm buffer_free(&compression_buffer); 38857429Smarkm buffer_compress_uninit(); 38957429Smarkm } 39092555Sdes cipher_cleanup(&send_context); 39192555Sdes cipher_cleanup(&receive_context); 39257429Smarkm} 39357429Smarkm 39457429Smarkm/* Sets remote side protocol flags. */ 39557429Smarkm 39657429Smarkmvoid 39776259Sgreenpacket_set_protocol_flags(u_int protocol_flags) 39857429Smarkm{ 39957429Smarkm remote_protocol_flags = protocol_flags; 40057429Smarkm} 40157429Smarkm 40257429Smarkm/* Returns the remote protocol flags set earlier by the above function. */ 40357429Smarkm 40476259Sgreenu_int 40592555Sdespacket_get_protocol_flags(void) 40657429Smarkm{ 40757429Smarkm return remote_protocol_flags; 40857429Smarkm} 40957429Smarkm 41057429Smarkm/* 41157429Smarkm * Starts packet compression from the next packet on in both directions. 41257429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. 41357429Smarkm */ 41457429Smarkm 41592555Sdesstatic void 41692555Sdespacket_init_compression(void) 41776259Sgreen{ 41876259Sgreen if (compression_buffer_ready == 1) 41976259Sgreen return; 42076259Sgreen compression_buffer_ready = 1; 42176259Sgreen buffer_init(&compression_buffer); 42276259Sgreen} 42376259Sgreen 42476259Sgreenvoid 42557429Smarkmpacket_start_compression(int level) 42657429Smarkm{ 42792555Sdes if (packet_compression && !compat20) 42857429Smarkm fatal("Compression already enabled."); 42957429Smarkm packet_compression = 1; 43076259Sgreen packet_init_compression(); 43176259Sgreen buffer_compress_init_send(level); 43276259Sgreen buffer_compress_init_recv(); 43357429Smarkm} 43457429Smarkm 43557429Smarkm/* 43657429Smarkm * Causes any further packets to be encrypted using the given key. The same 43757429Smarkm * key is used for both sending and reception. However, both directions are 43857429Smarkm * encrypted independently of each other. 43957429Smarkm */ 44098675Sdes 44157429Smarkmvoid 44276259Sgreenpacket_set_encryption_key(const u_char *key, u_int keylen, 44369587Sgreen int number) 44457429Smarkm{ 44569587Sgreen Cipher *cipher = cipher_by_number(number); 446106121Sdes 44769587Sgreen if (cipher == NULL) 44869587Sgreen fatal("packet_set_encryption_key: unknown cipher number %d", number); 44960573Skris if (keylen < 20) 45069587Sgreen fatal("packet_set_encryption_key: keylen too small: %d", keylen); 45198675Sdes if (keylen > SSH_SESSION_KEY_LENGTH) 45298675Sdes fatal("packet_set_encryption_key: keylen too big: %d", keylen); 45398675Sdes memcpy(ssh1_key, key, keylen); 45498675Sdes ssh1_keylen = keylen; 45592555Sdes cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); 45692555Sdes cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); 45757429Smarkm} 45857429Smarkm 45998675Sdesu_int 46098675Sdespacket_get_encryption_key(u_char *key) 46198675Sdes{ 46298675Sdes if (key == NULL) 46398675Sdes return (ssh1_keylen); 46498675Sdes memcpy(key, ssh1_key, ssh1_keylen); 46598675Sdes return (ssh1_keylen); 46698675Sdes} 46798675Sdes 46892555Sdes/* Start constructing a packet to send. */ 46957429Smarkmvoid 47092555Sdespacket_start(u_char type) 47157429Smarkm{ 47292555Sdes u_char buf[9]; 47392555Sdes int len; 47457429Smarkm 47592555Sdes DBG(debug("packet_start[%d]", type)); 47692555Sdes len = compat20 ? 6 : 9; 47792555Sdes memset(buf, 0, len - 1); 47892555Sdes buf[len - 1] = type; 47957429Smarkm buffer_clear(&outgoing_packet); 48092555Sdes buffer_append(&outgoing_packet, buf, len); 48157429Smarkm} 48257429Smarkm 48392555Sdes/* Append payload. */ 48460573Skrisvoid 48557429Smarkmpacket_put_char(int value) 48657429Smarkm{ 48757429Smarkm char ch = value; 488106121Sdes 48957429Smarkm buffer_append(&outgoing_packet, &ch, 1); 49057429Smarkm} 491162852Sdes 49257429Smarkmvoid 49376259Sgreenpacket_put_int(u_int value) 49457429Smarkm{ 49557429Smarkm buffer_put_int(&outgoing_packet, value); 49657429Smarkm} 497162852Sdes 49857429Smarkmvoid 49992555Sdespacket_put_string(const void *buf, u_int len) 50057429Smarkm{ 50157429Smarkm buffer_put_string(&outgoing_packet, buf, len); 50257429Smarkm} 503162852Sdes 50460573Skrisvoid 50560573Skrispacket_put_cstring(const char *str) 50660573Skris{ 50792555Sdes buffer_put_cstring(&outgoing_packet, str); 50860573Skris} 509162852Sdes 51060573Skrisvoid 51192555Sdespacket_put_raw(const void *buf, u_int len) 51260573Skris{ 51360573Skris buffer_append(&outgoing_packet, buf, len); 51460573Skris} 515162852Sdes 51657429Smarkmvoid 51757429Smarkmpacket_put_bignum(BIGNUM * value) 51857429Smarkm{ 51957429Smarkm buffer_put_bignum(&outgoing_packet, value); 52057429Smarkm} 521162852Sdes 52260573Skrisvoid 52360573Skrispacket_put_bignum2(BIGNUM * value) 52460573Skris{ 52560573Skris buffer_put_bignum2(&outgoing_packet, value); 52660573Skris} 52757429Smarkm 52857429Smarkm/* 52957429Smarkm * Finalizes and sends the packet. If the encryption key has been set, 53057429Smarkm * encrypts the packet before sending. 53157429Smarkm */ 53257429Smarkm 53392555Sdesstatic void 53476259Sgreenpacket_send1(void) 53557429Smarkm{ 53692555Sdes u_char buf[8], *cp; 53757429Smarkm int i, padding, len; 53876259Sgreen u_int checksum; 539137015Sdes u_int32_t rnd = 0; 54057429Smarkm 54157429Smarkm /* 54257429Smarkm * If using packet compression, compress the payload of the outgoing 54357429Smarkm * packet. 54457429Smarkm */ 54557429Smarkm if (packet_compression) { 54657429Smarkm buffer_clear(&compression_buffer); 54757429Smarkm /* Skip padding. */ 54857429Smarkm buffer_consume(&outgoing_packet, 8); 54957429Smarkm /* padding */ 55057429Smarkm buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); 55157429Smarkm buffer_compress(&outgoing_packet, &compression_buffer); 55257429Smarkm buffer_clear(&outgoing_packet); 55357429Smarkm buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 55492555Sdes buffer_len(&compression_buffer)); 55557429Smarkm } 55657429Smarkm /* Compute packet length without padding (add checksum, remove padding). */ 55757429Smarkm len = buffer_len(&outgoing_packet) + 4 - 8; 55857429Smarkm 55960573Skris /* Insert padding. Initialized to zero in packet_start1() */ 56057429Smarkm padding = 8 - len % 8; 56192555Sdes if (!send_context.plaintext) { 56257429Smarkm cp = buffer_ptr(&outgoing_packet); 56357429Smarkm for (i = 0; i < padding; i++) { 56457429Smarkm if (i % 4 == 0) 565137015Sdes rnd = arc4random(); 566137015Sdes cp[7 - i] = rnd & 0xff; 567137015Sdes rnd >>= 8; 56857429Smarkm } 56957429Smarkm } 57057429Smarkm buffer_consume(&outgoing_packet, 8 - padding); 57157429Smarkm 57257429Smarkm /* Add check bytes. */ 57392555Sdes checksum = ssh_crc32(buffer_ptr(&outgoing_packet), 57465668Skris buffer_len(&outgoing_packet)); 575162852Sdes put_u32(buf, checksum); 57657429Smarkm buffer_append(&outgoing_packet, buf, 4); 57757429Smarkm 57857429Smarkm#ifdef PACKET_DEBUG 57957429Smarkm fprintf(stderr, "packet_send plain: "); 58057429Smarkm buffer_dump(&outgoing_packet); 58157429Smarkm#endif 58257429Smarkm 58357429Smarkm /* Append to output. */ 584162852Sdes put_u32(buf, len); 58557429Smarkm buffer_append(&output, buf, 4); 58692555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 58792555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 58892555Sdes buffer_len(&outgoing_packet)); 58957429Smarkm 59057429Smarkm#ifdef PACKET_DEBUG 59157429Smarkm fprintf(stderr, "encrypted: "); 59257429Smarkm buffer_dump(&output); 59357429Smarkm#endif 59457429Smarkm 59557429Smarkm buffer_clear(&outgoing_packet); 59657429Smarkm 59757429Smarkm /* 598157016Sdes * Note that the packet is now only buffered in output. It won't be 59957429Smarkm * actually sent until packet_write_wait or packet_write_poll is 60057429Smarkm * called. 60157429Smarkm */ 60257429Smarkm} 60357429Smarkm 60498675Sdesvoid 60576259Sgreenset_newkeys(int mode) 60676259Sgreen{ 60776259Sgreen Enc *enc; 60876259Sgreen Mac *mac; 60976259Sgreen Comp *comp; 61076259Sgreen CipherContext *cc; 611124208Sdes u_int64_t *max_blocks; 612137015Sdes int crypt_type; 61376259Sgreen 614113908Sdes debug2("set_newkeys: mode %d", mode); 61576259Sgreen 61692555Sdes if (mode == MODE_OUT) { 61792555Sdes cc = &send_context; 618137015Sdes crypt_type = CIPHER_ENCRYPT; 619124208Sdes p_send.packets = p_send.blocks = 0; 620124208Sdes max_blocks = &max_blocks_out; 62192555Sdes } else { 62292555Sdes cc = &receive_context; 623137015Sdes crypt_type = CIPHER_DECRYPT; 624124208Sdes p_read.packets = p_read.blocks = 0; 625124208Sdes max_blocks = &max_blocks_in; 62692555Sdes } 62776259Sgreen if (newkeys[mode] != NULL) { 628113908Sdes debug("set_newkeys: rekeying"); 62992555Sdes cipher_cleanup(cc); 63076259Sgreen enc = &newkeys[mode]->enc; 63176259Sgreen mac = &newkeys[mode]->mac; 63276259Sgreen comp = &newkeys[mode]->comp; 63376259Sgreen memset(mac->key, 0, mac->key_len); 63476259Sgreen xfree(enc->name); 63576259Sgreen xfree(enc->iv); 63676259Sgreen xfree(enc->key); 63776259Sgreen xfree(mac->name); 63876259Sgreen xfree(mac->key); 63976259Sgreen xfree(comp->name); 64076259Sgreen xfree(newkeys[mode]); 64176259Sgreen } 64276259Sgreen newkeys[mode] = kex_get_newkeys(mode); 64376259Sgreen if (newkeys[mode] == NULL) 64476259Sgreen fatal("newkeys: no keys for mode %d", mode); 64576259Sgreen enc = &newkeys[mode]->enc; 64676259Sgreen mac = &newkeys[mode]->mac; 64776259Sgreen comp = &newkeys[mode]->comp; 64876259Sgreen if (mac->md != NULL) 64976259Sgreen mac->enabled = 1; 65076259Sgreen DBG(debug("cipher_init_context: %d", mode)); 65192555Sdes cipher_init(cc, enc->cipher, enc->key, enc->key_len, 652137015Sdes enc->iv, enc->block_size, crypt_type); 65398675Sdes /* Deleting the keys does not gain extra security */ 65498675Sdes /* memset(enc->iv, 0, enc->block_size); 65598675Sdes memset(enc->key, 0, enc->key_len); */ 656149749Sdes if ((comp->type == COMP_ZLIB || 657149749Sdes (comp->type == COMP_DELAYED && after_authentication)) && 658149749Sdes comp->enabled == 0) { 65976259Sgreen packet_init_compression(); 66076259Sgreen if (mode == MODE_OUT) 66176259Sgreen buffer_compress_init_send(6); 66276259Sgreen else 66376259Sgreen buffer_compress_init_recv(); 66476259Sgreen comp->enabled = 1; 66576259Sgreen } 666124208Sdes /* 667124208Sdes * The 2^(blocksize*2) limit is too expensive for 3DES, 668124208Sdes * blowfish, etc, so enforce a 1GB limit for small blocksizes. 669124208Sdes */ 670124208Sdes if (enc->block_size >= 16) 671124208Sdes *max_blocks = (u_int64_t)1 << (enc->block_size*2); 672124208Sdes else 673124208Sdes *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; 674124208Sdes if (rekey_limit) 675124208Sdes *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size); 67676259Sgreen} 67776259Sgreen 67857429Smarkm/* 679149749Sdes * Delayed compression for SSH2 is enabled after authentication: 680162852Sdes * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, 681149749Sdes * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received. 682149749Sdes */ 683149749Sdesstatic void 684149749Sdespacket_enable_delayed_compress(void) 685149749Sdes{ 686149749Sdes Comp *comp = NULL; 687149749Sdes int mode; 688149749Sdes 689149749Sdes /* 690149749Sdes * Remember that we are past the authentication step, so rekeying 691149749Sdes * with COMP_DELAYED will turn on compression immediately. 692149749Sdes */ 693149749Sdes after_authentication = 1; 694149749Sdes for (mode = 0; mode < MODE_MAX; mode++) { 695162852Sdes /* protocol error: USERAUTH_SUCCESS received before NEWKEYS */ 696162852Sdes if (newkeys[mode] == NULL) 697162852Sdes continue; 698149749Sdes comp = &newkeys[mode]->comp; 699149749Sdes if (comp && !comp->enabled && comp->type == COMP_DELAYED) { 700149749Sdes packet_init_compression(); 701149749Sdes if (mode == MODE_OUT) 702149749Sdes buffer_compress_init_send(6); 703149749Sdes else 704149749Sdes buffer_compress_init_recv(); 705149749Sdes comp->enabled = 1; 706149749Sdes } 707149749Sdes } 708149749Sdes} 709149749Sdes 710149749Sdes/* 71160573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 71260573Skris */ 71392555Sdesstatic void 714124208Sdespacket_send2_wrapped(void) 71560573Skris{ 71692555Sdes u_char type, *cp, *macbuf = NULL; 71792555Sdes u_char padlen, pad; 71876259Sgreen u_int packet_length = 0; 71992555Sdes u_int i, len; 720137015Sdes u_int32_t rnd = 0; 72160573Skris Enc *enc = NULL; 72260573Skris Mac *mac = NULL; 72360573Skris Comp *comp = NULL; 72460573Skris int block_size; 72560573Skris 72676259Sgreen if (newkeys[MODE_OUT] != NULL) { 72776259Sgreen enc = &newkeys[MODE_OUT]->enc; 72876259Sgreen mac = &newkeys[MODE_OUT]->mac; 72976259Sgreen comp = &newkeys[MODE_OUT]->comp; 73060573Skris } 73192555Sdes block_size = enc ? enc->block_size : 8; 73260573Skris 73360573Skris cp = buffer_ptr(&outgoing_packet); 73492555Sdes type = cp[5]; 73560573Skris 73660573Skris#ifdef PACKET_DEBUG 73760573Skris fprintf(stderr, "plain: "); 73860573Skris buffer_dump(&outgoing_packet); 73960573Skris#endif 74060573Skris 74160573Skris if (comp && comp->enabled) { 74260573Skris len = buffer_len(&outgoing_packet); 74360573Skris /* skip header, compress only payload */ 74460573Skris buffer_consume(&outgoing_packet, 5); 74560573Skris buffer_clear(&compression_buffer); 74660573Skris buffer_compress(&outgoing_packet, &compression_buffer); 74760573Skris buffer_clear(&outgoing_packet); 74860573Skris buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); 74960573Skris buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 75060573Skris buffer_len(&compression_buffer)); 75160573Skris DBG(debug("compression: raw %d compressed %d", len, 75260573Skris buffer_len(&outgoing_packet))); 75360573Skris } 75460573Skris 75560573Skris /* sizeof (packet_len + pad_len + payload) */ 75660573Skris len = buffer_len(&outgoing_packet); 75760573Skris 75860573Skris /* 75960573Skris * calc size of padding, alloc space, get random data, 76060573Skris * minimum padding is 4 bytes 76160573Skris */ 76260573Skris padlen = block_size - (len % block_size); 76360573Skris if (padlen < 4) 76460573Skris padlen += block_size; 76592555Sdes if (extra_pad) { 76692555Sdes /* will wrap if extra_pad+padlen > 255 */ 76792555Sdes extra_pad = roundup(extra_pad, block_size); 76892555Sdes pad = extra_pad - ((len + padlen) % extra_pad); 76998675Sdes debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 77092555Sdes pad, len, padlen, extra_pad); 77192555Sdes padlen += pad; 77292555Sdes extra_pad = 0; 77392555Sdes } 77492555Sdes cp = buffer_append_space(&outgoing_packet, padlen); 77592555Sdes if (enc && !send_context.plaintext) { 77660573Skris /* random padding */ 77760573Skris for (i = 0; i < padlen; i++) { 77860573Skris if (i % 4 == 0) 779137015Sdes rnd = arc4random(); 780137015Sdes cp[i] = rnd & 0xff; 781137015Sdes rnd >>= 8; 78260573Skris } 78360573Skris } else { 78460573Skris /* clear padding */ 78560573Skris memset(cp, 0, padlen); 78660573Skris } 78760573Skris /* packet_length includes payload, padding and padding length field */ 78860573Skris packet_length = buffer_len(&outgoing_packet) - 4; 78960573Skris cp = buffer_ptr(&outgoing_packet); 790162852Sdes put_u32(cp, packet_length); 79192555Sdes cp[4] = padlen; 79260573Skris DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); 79360573Skris 79460573Skris /* compute MAC over seqnr and packet(length fields, payload, padding) */ 79560573Skris if (mac && mac->enabled) { 796124208Sdes macbuf = mac_compute(mac, p_send.seqnr, 79792555Sdes buffer_ptr(&outgoing_packet), 79876259Sgreen buffer_len(&outgoing_packet)); 799124208Sdes DBG(debug("done calc MAC out #%d", p_send.seqnr)); 80060573Skris } 80160573Skris /* encrypt packet and append to output buffer. */ 80292555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 80392555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 80460573Skris buffer_len(&outgoing_packet)); 80560573Skris /* append unencrypted MAC */ 80660573Skris if (mac && mac->enabled) 807162852Sdes buffer_append(&output, macbuf, mac->mac_len); 80860573Skris#ifdef PACKET_DEBUG 80960573Skris fprintf(stderr, "encrypted: "); 81060573Skris buffer_dump(&output); 81160573Skris#endif 81260573Skris /* increment sequence number for outgoing packets */ 813124208Sdes if (++p_send.seqnr == 0) 814124208Sdes logit("outgoing seqnr wraps around"); 815124208Sdes if (++p_send.packets == 0) 816124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 817124208Sdes fatal("XXX too many packets with same key"); 818124208Sdes p_send.blocks += (packet_length + 4) / block_size; 81960573Skris buffer_clear(&outgoing_packet); 82060573Skris 82176259Sgreen if (type == SSH2_MSG_NEWKEYS) 82276259Sgreen set_newkeys(MODE_OUT); 823149749Sdes else if (type == SSH2_MSG_USERAUTH_SUCCESS && server_side) 824149749Sdes packet_enable_delayed_compress(); 82560573Skris} 82660573Skris 827124208Sdesstatic void 828124208Sdespacket_send2(void) 829124208Sdes{ 830124208Sdes static int rekeying = 0; 831124208Sdes struct packet *p; 832124208Sdes u_char type, *cp; 833124208Sdes 834124208Sdes cp = buffer_ptr(&outgoing_packet); 835124208Sdes type = cp[5]; 836124208Sdes 837124208Sdes /* during rekeying we can only send key exchange messages */ 838124208Sdes if (rekeying) { 839124208Sdes if (!((type >= SSH2_MSG_TRANSPORT_MIN) && 840124208Sdes (type <= SSH2_MSG_TRANSPORT_MAX))) { 841124208Sdes debug("enqueue packet: %u", type); 842124208Sdes p = xmalloc(sizeof(*p)); 843124208Sdes p->type = type; 844124208Sdes memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); 845124208Sdes buffer_init(&outgoing_packet); 846124208Sdes TAILQ_INSERT_TAIL(&outgoing, p, next); 847124208Sdes return; 848124208Sdes } 849124208Sdes } 850124208Sdes 851124208Sdes /* rekeying starts with sending KEXINIT */ 852124208Sdes if (type == SSH2_MSG_KEXINIT) 853124208Sdes rekeying = 1; 854124208Sdes 855124208Sdes packet_send2_wrapped(); 856124208Sdes 857124208Sdes /* after a NEWKEYS message we can send the complete queue */ 858124208Sdes if (type == SSH2_MSG_NEWKEYS) { 859124208Sdes rekeying = 0; 860124208Sdes while ((p = TAILQ_FIRST(&outgoing))) { 861124208Sdes type = p->type; 862124208Sdes debug("dequeue packet: %u", type); 863124208Sdes buffer_free(&outgoing_packet); 864124208Sdes memcpy(&outgoing_packet, &p->payload, 865124208Sdes sizeof(Buffer)); 866124208Sdes TAILQ_REMOVE(&outgoing, p, next); 867124208Sdes xfree(p); 868124208Sdes packet_send2_wrapped(); 869124208Sdes } 870124208Sdes } 871124208Sdes} 872124208Sdes 87360573Skrisvoid 87492555Sdespacket_send(void) 87560573Skris{ 87692555Sdes if (compat20) 87760573Skris packet_send2(); 87860573Skris else 87960573Skris packet_send1(); 88060573Skris DBG(debug("packet_send done")); 88160573Skris} 88260573Skris 88360573Skris/* 88457429Smarkm * Waits until a packet has been received, and returns its type. Note that 88557429Smarkm * no other data is processed until this returns, so this function should not 88657429Smarkm * be used during the interactive session. 88757429Smarkm */ 88857429Smarkm 88957429Smarkmint 89092555Sdespacket_read_seqnr(u_int32_t *seqnr_p) 89157429Smarkm{ 89257429Smarkm int type, len; 89376259Sgreen fd_set *setp; 89457429Smarkm char buf[8192]; 89560573Skris DBG(debug("packet_read()")); 89657429Smarkm 897162852Sdes setp = (fd_set *)xcalloc(howmany(connection_in+1, NFDBITS), 89876259Sgreen sizeof(fd_mask)); 89976259Sgreen 90057429Smarkm /* Since we are blocking, ensure that all written packets have been sent. */ 90157429Smarkm packet_write_wait(); 90257429Smarkm 90357429Smarkm /* Stay in the loop until we have received a complete packet. */ 90457429Smarkm for (;;) { 90557429Smarkm /* Try to read a packet from the buffer. */ 90692555Sdes type = packet_read_poll_seqnr(seqnr_p); 90792555Sdes if (!compat20 && ( 90860573Skris type == SSH_SMSG_SUCCESS 90957429Smarkm || type == SSH_SMSG_FAILURE 91057429Smarkm || type == SSH_CMSG_EOF 91160573Skris || type == SSH_CMSG_EXIT_CONFIRMATION)) 91292555Sdes packet_check_eom(); 91357429Smarkm /* If we got a packet, return it. */ 91476259Sgreen if (type != SSH_MSG_NONE) { 91576259Sgreen xfree(setp); 91657429Smarkm return type; 91776259Sgreen } 91857429Smarkm /* 91957429Smarkm * Otherwise, wait for some data to arrive, add it to the 92057429Smarkm * buffer, and try again. 92157429Smarkm */ 92276259Sgreen memset(setp, 0, howmany(connection_in + 1, NFDBITS) * 92376259Sgreen sizeof(fd_mask)); 92476259Sgreen FD_SET(connection_in, setp); 92557429Smarkm 92657429Smarkm /* Wait for some data to arrive. */ 92776259Sgreen while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && 92876259Sgreen (errno == EAGAIN || errno == EINTR)) 92976259Sgreen ; 93057429Smarkm 93157429Smarkm /* Read data from the socket. */ 93257429Smarkm len = read(connection_in, buf, sizeof(buf)); 93357429Smarkm if (len == 0) { 934124208Sdes logit("Connection closed by %.200s", get_remote_ipaddr()); 935126274Sdes cleanup_exit(255); 93657429Smarkm } 93757429Smarkm if (len < 0) 93857429Smarkm fatal("Read from socket failed: %.100s", strerror(errno)); 93957429Smarkm /* Append it to the buffer. */ 94057429Smarkm packet_process_incoming(buf, len); 94157429Smarkm } 94257429Smarkm /* NOTREACHED */ 94357429Smarkm} 94457429Smarkm 94592555Sdesint 94692555Sdespacket_read(void) 94792555Sdes{ 94892555Sdes return packet_read_seqnr(NULL); 94992555Sdes} 95092555Sdes 95157429Smarkm/* 95257429Smarkm * Waits until a packet has been received, verifies that its type matches 95357429Smarkm * that given, and gives a fatal error and exits if there is a mismatch. 95457429Smarkm */ 95557429Smarkm 95657429Smarkmvoid 95792555Sdespacket_read_expect(int expected_type) 95857429Smarkm{ 95957429Smarkm int type; 96057429Smarkm 96192555Sdes type = packet_read(); 96257429Smarkm if (type != expected_type) 96357429Smarkm packet_disconnect("Protocol error: expected packet type %d, got %d", 96460573Skris expected_type, type); 96557429Smarkm} 96657429Smarkm 96757429Smarkm/* Checks if a full packet is available in the data received so far via 96857429Smarkm * packet_process_incoming. If so, reads the packet; otherwise returns 96957429Smarkm * SSH_MSG_NONE. This does not wait for data from the connection. 97057429Smarkm * 97157429Smarkm * SSH_MSG_DISCONNECT is handled specially here. Also, 97257429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned 97357429Smarkm * to higher levels. 97457429Smarkm */ 97557429Smarkm 97692555Sdesstatic int 97792555Sdespacket_read_poll1(void) 97857429Smarkm{ 97976259Sgreen u_int len, padded_len; 98092555Sdes u_char *cp, type; 98176259Sgreen u_int checksum, stored_checksum; 98257429Smarkm 98357429Smarkm /* Check if input size is less than minimum packet size. */ 98457429Smarkm if (buffer_len(&input) < 4 + 8) 98557429Smarkm return SSH_MSG_NONE; 98657429Smarkm /* Get length of incoming packet. */ 98792555Sdes cp = buffer_ptr(&input); 988162852Sdes len = get_u32(cp); 98957429Smarkm if (len < 1 + 2 + 2 || len > 256 * 1024) 990113908Sdes packet_disconnect("Bad packet length %u.", len); 99157429Smarkm padded_len = (len + 8) & ~7; 99257429Smarkm 99357429Smarkm /* Check if the packet has been entirely received. */ 99457429Smarkm if (buffer_len(&input) < 4 + padded_len) 99557429Smarkm return SSH_MSG_NONE; 99657429Smarkm 99757429Smarkm /* The entire packet is in buffer. */ 99857429Smarkm 99957429Smarkm /* Consume packet length. */ 100057429Smarkm buffer_consume(&input, 4); 100157429Smarkm 100292555Sdes /* 100392555Sdes * Cryptographic attack detector for ssh 100492555Sdes * (C)1998 CORE-SDI, Buenos Aires Argentina 100592555Sdes * Ariel Futoransky(futo@core-sdi.com) 100692555Sdes */ 1007162852Sdes if (!receive_context.plaintext) { 1008162852Sdes switch (detect_attack(buffer_ptr(&input), padded_len)) { 1009162852Sdes case DEATTACK_DETECTED: 1010162852Sdes packet_disconnect("crc32 compensation attack: " 1011162852Sdes "network attack detected"); 1012162852Sdes case DEATTACK_DOS_DETECTED: 1013162852Sdes packet_disconnect("deattack denial of " 1014162852Sdes "service detected"); 1015162852Sdes } 1016162852Sdes } 101792555Sdes 101892555Sdes /* Decrypt data to incoming_packet. */ 101957429Smarkm buffer_clear(&incoming_packet); 102092555Sdes cp = buffer_append_space(&incoming_packet, padded_len); 102192555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); 102292555Sdes 102357429Smarkm buffer_consume(&input, padded_len); 102457429Smarkm 102557429Smarkm#ifdef PACKET_DEBUG 102657429Smarkm fprintf(stderr, "read_poll plain: "); 102757429Smarkm buffer_dump(&incoming_packet); 102857429Smarkm#endif 102957429Smarkm 103057429Smarkm /* Compute packet checksum. */ 103192555Sdes checksum = ssh_crc32(buffer_ptr(&incoming_packet), 103260573Skris buffer_len(&incoming_packet) - 4); 103357429Smarkm 103457429Smarkm /* Skip padding. */ 103557429Smarkm buffer_consume(&incoming_packet, 8 - len % 8); 103657429Smarkm 103757429Smarkm /* Test check bytes. */ 103857429Smarkm if (len != buffer_len(&incoming_packet)) 103992555Sdes packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 104060573Skris len, buffer_len(&incoming_packet)); 104157429Smarkm 104292555Sdes cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; 1043162852Sdes stored_checksum = get_u32(cp); 104457429Smarkm if (checksum != stored_checksum) 104557429Smarkm packet_disconnect("Corrupted check bytes on input."); 104657429Smarkm buffer_consume_end(&incoming_packet, 4); 104757429Smarkm 104857429Smarkm if (packet_compression) { 104957429Smarkm buffer_clear(&compression_buffer); 105057429Smarkm buffer_uncompress(&incoming_packet, &compression_buffer); 105157429Smarkm buffer_clear(&incoming_packet); 105257429Smarkm buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 105360573Skris buffer_len(&compression_buffer)); 105457429Smarkm } 105592555Sdes type = buffer_get_char(&incoming_packet); 1056146998Sdes if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) 1057146998Sdes packet_disconnect("Invalid ssh1 packet type: %d", type); 105892555Sdes return type; 105960573Skris} 106057429Smarkm 106192555Sdesstatic int 106292555Sdespacket_read_poll2(u_int32_t *seqnr_p) 106360573Skris{ 106476259Sgreen static u_int packet_length = 0; 106576259Sgreen u_int padlen, need; 106692555Sdes u_char *macbuf, *cp, type; 1067149749Sdes u_int maclen, block_size; 106860573Skris Enc *enc = NULL; 106960573Skris Mac *mac = NULL; 107060573Skris Comp *comp = NULL; 107157429Smarkm 107276259Sgreen if (newkeys[MODE_IN] != NULL) { 107376259Sgreen enc = &newkeys[MODE_IN]->enc; 107476259Sgreen mac = &newkeys[MODE_IN]->mac; 107576259Sgreen comp = &newkeys[MODE_IN]->comp; 107657429Smarkm } 107760573Skris maclen = mac && mac->enabled ? mac->mac_len : 0; 107892555Sdes block_size = enc ? enc->block_size : 8; 107960573Skris 108060573Skris if (packet_length == 0) { 108160573Skris /* 108260573Skris * check if input size is less than the cipher block size, 108360573Skris * decrypt first block and extract length of incoming packet 108460573Skris */ 108560573Skris if (buffer_len(&input) < block_size) 108660573Skris return SSH_MSG_NONE; 108760573Skris buffer_clear(&incoming_packet); 108892555Sdes cp = buffer_append_space(&incoming_packet, block_size); 108992555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), 109060573Skris block_size); 109192555Sdes cp = buffer_ptr(&incoming_packet); 1092162852Sdes packet_length = get_u32(cp); 109360573Skris if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 1094124208Sdes#ifdef PACKET_DEBUG 109560573Skris buffer_dump(&incoming_packet); 1096124208Sdes#endif 1097113908Sdes packet_disconnect("Bad packet length %u.", packet_length); 109860573Skris } 1099113908Sdes DBG(debug("input: packet len %u", packet_length+4)); 110060573Skris buffer_consume(&input, block_size); 110160573Skris } 110260573Skris /* we have a partial packet of block_size bytes */ 110360573Skris need = 4 + packet_length - block_size; 110460573Skris DBG(debug("partial packet %d, need %d, maclen %d", block_size, 110560573Skris need, maclen)); 110660573Skris if (need % block_size != 0) 110760573Skris fatal("padding error: need %d block %d mod %d", 110860573Skris need, block_size, need % block_size); 110960573Skris /* 111060573Skris * check if the entire packet has been received and 111160573Skris * decrypt into incoming_packet 111260573Skris */ 111360573Skris if (buffer_len(&input) < need + maclen) 111460573Skris return SSH_MSG_NONE; 111560573Skris#ifdef PACKET_DEBUG 111660573Skris fprintf(stderr, "read_poll enc/full: "); 111760573Skris buffer_dump(&input); 111860573Skris#endif 111992555Sdes cp = buffer_append_space(&incoming_packet, need); 112092555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); 112160573Skris buffer_consume(&input, need); 112260573Skris /* 112360573Skris * compute MAC over seqnr and packet, 112460573Skris * increment sequence number for incoming packet 112560573Skris */ 112660573Skris if (mac && mac->enabled) { 1127124208Sdes macbuf = mac_compute(mac, p_read.seqnr, 112892555Sdes buffer_ptr(&incoming_packet), 112976259Sgreen buffer_len(&incoming_packet)); 113060573Skris if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 113169587Sgreen packet_disconnect("Corrupted MAC on input."); 1132124208Sdes DBG(debug("MAC #%d ok", p_read.seqnr)); 113360573Skris buffer_consume(&input, mac->mac_len); 113460573Skris } 113592555Sdes if (seqnr_p != NULL) 1136124208Sdes *seqnr_p = p_read.seqnr; 1137124208Sdes if (++p_read.seqnr == 0) 1138124208Sdes logit("incoming seqnr wraps around"); 1139124208Sdes if (++p_read.packets == 0) 1140124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 1141124208Sdes fatal("XXX too many packets with same key"); 1142124208Sdes p_read.blocks += (packet_length + 4) / block_size; 114360573Skris 114460573Skris /* get padlen */ 114592555Sdes cp = buffer_ptr(&incoming_packet); 114692555Sdes padlen = cp[4]; 114760573Skris DBG(debug("input: padlen %d", padlen)); 114860573Skris if (padlen < 4) 114960573Skris packet_disconnect("Corrupted padlen %d on input.", padlen); 115060573Skris 115160573Skris /* skip packet size + padlen, discard padding */ 115260573Skris buffer_consume(&incoming_packet, 4 + 1); 115360573Skris buffer_consume_end(&incoming_packet, padlen); 115460573Skris 115560573Skris DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); 115660573Skris if (comp && comp->enabled) { 115760573Skris buffer_clear(&compression_buffer); 115860573Skris buffer_uncompress(&incoming_packet, &compression_buffer); 115960573Skris buffer_clear(&incoming_packet); 116060573Skris buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 116160573Skris buffer_len(&compression_buffer)); 1162106121Sdes DBG(debug("input: len after de-compress %d", 1163106121Sdes buffer_len(&incoming_packet))); 116460573Skris } 116560573Skris /* 116660573Skris * get packet type, implies consume. 116760573Skris * return length of payload (without type field) 116860573Skris */ 116992555Sdes type = buffer_get_char(&incoming_packet); 1170146998Sdes if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN) 1171146998Sdes packet_disconnect("Invalid ssh2 packet type: %d", type); 117276259Sgreen if (type == SSH2_MSG_NEWKEYS) 117376259Sgreen set_newkeys(MODE_IN); 1174149749Sdes else if (type == SSH2_MSG_USERAUTH_SUCCESS && !server_side) 1175149749Sdes packet_enable_delayed_compress(); 117660573Skris#ifdef PACKET_DEBUG 117776259Sgreen fprintf(stderr, "read/plain[%d]:\r\n", type); 117860573Skris buffer_dump(&incoming_packet); 117960573Skris#endif 118092555Sdes /* reset for next packet */ 118192555Sdes packet_length = 0; 118292555Sdes return type; 118357429Smarkm} 118457429Smarkm 118560573Skrisint 118692555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p) 118760573Skris{ 118899060Sdes u_int reason, seqnr; 118992555Sdes u_char type; 119060573Skris char *msg; 119192555Sdes 119260573Skris for (;;) { 119392555Sdes if (compat20) { 119492555Sdes type = packet_read_poll2(seqnr_p); 119592555Sdes if (type) 119660573Skris DBG(debug("received packet type %d", type)); 119792555Sdes switch (type) { 119860573Skris case SSH2_MSG_IGNORE: 119960573Skris break; 120060573Skris case SSH2_MSG_DEBUG: 120160573Skris packet_get_char(); 120260573Skris msg = packet_get_string(NULL); 120360573Skris debug("Remote: %.900s", msg); 120460573Skris xfree(msg); 120560573Skris msg = packet_get_string(NULL); 120660573Skris xfree(msg); 120760573Skris break; 120860573Skris case SSH2_MSG_DISCONNECT: 120960573Skris reason = packet_get_int(); 121060573Skris msg = packet_get_string(NULL); 1211124208Sdes logit("Received disconnect from %s: %u: %.400s", 121299060Sdes get_remote_ipaddr(), reason, msg); 121360573Skris xfree(msg); 1214126274Sdes cleanup_exit(255); 121560573Skris break; 121692555Sdes case SSH2_MSG_UNIMPLEMENTED: 121792555Sdes seqnr = packet_get_int(); 121899060Sdes debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 121999060Sdes seqnr); 122092555Sdes break; 122160573Skris default: 122260573Skris return type; 122376259Sgreen } 122460573Skris } else { 122592555Sdes type = packet_read_poll1(); 122692555Sdes switch (type) { 122760573Skris case SSH_MSG_IGNORE: 122860573Skris break; 122960573Skris case SSH_MSG_DEBUG: 123060573Skris msg = packet_get_string(NULL); 123160573Skris debug("Remote: %.900s", msg); 123260573Skris xfree(msg); 123360573Skris break; 123460573Skris case SSH_MSG_DISCONNECT: 123560573Skris msg = packet_get_string(NULL); 1236124208Sdes logit("Received disconnect from %s: %.400s", 123799060Sdes get_remote_ipaddr(), msg); 1238126274Sdes cleanup_exit(255); 123960573Skris xfree(msg); 124060573Skris break; 124160573Skris default: 124292555Sdes if (type) 124360573Skris DBG(debug("received packet type %d", type)); 124460573Skris return type; 124576259Sgreen } 124660573Skris } 124760573Skris } 124860573Skris} 124960573Skris 125092555Sdesint 125192555Sdespacket_read_poll(void) 125292555Sdes{ 125392555Sdes return packet_read_poll_seqnr(NULL); 125492555Sdes} 125592555Sdes 125657429Smarkm/* 125757429Smarkm * Buffers the given amount of input characters. This is intended to be used 125857429Smarkm * together with packet_read_poll. 125957429Smarkm */ 126057429Smarkm 126157429Smarkmvoid 126276259Sgreenpacket_process_incoming(const char *buf, u_int len) 126357429Smarkm{ 126457429Smarkm buffer_append(&input, buf, len); 126557429Smarkm} 126657429Smarkm 126757429Smarkm/* Returns a character from the packet. */ 126857429Smarkm 126976259Sgreenu_int 127092555Sdespacket_get_char(void) 127157429Smarkm{ 127257429Smarkm char ch; 1273106121Sdes 127457429Smarkm buffer_get(&incoming_packet, &ch, 1); 127576259Sgreen return (u_char) ch; 127657429Smarkm} 127757429Smarkm 127857429Smarkm/* Returns an integer from the packet data. */ 127957429Smarkm 128076259Sgreenu_int 128192555Sdespacket_get_int(void) 128257429Smarkm{ 128357429Smarkm return buffer_get_int(&incoming_packet); 128457429Smarkm} 128557429Smarkm 128657429Smarkm/* 128757429Smarkm * Returns an arbitrary precision integer from the packet data. The integer 128857429Smarkm * must have been initialized before this call. 128957429Smarkm */ 129057429Smarkm 129157429Smarkmvoid 129292555Sdespacket_get_bignum(BIGNUM * value) 129357429Smarkm{ 129492555Sdes buffer_get_bignum(&incoming_packet, value); 129557429Smarkm} 129657429Smarkm 129760573Skrisvoid 129892555Sdespacket_get_bignum2(BIGNUM * value) 129960573Skris{ 130092555Sdes buffer_get_bignum2(&incoming_packet, value); 130160573Skris} 130260573Skris 130392555Sdesvoid * 1304149749Sdespacket_get_raw(u_int *length_ptr) 130560573Skris{ 1306149749Sdes u_int bytes = buffer_len(&incoming_packet); 1307106121Sdes 130860573Skris if (length_ptr != NULL) 130960573Skris *length_ptr = bytes; 131060573Skris return buffer_ptr(&incoming_packet); 131160573Skris} 131260573Skris 131360573Skrisint 131460573Skrispacket_remaining(void) 131560573Skris{ 131660573Skris return buffer_len(&incoming_packet); 131760573Skris} 131860573Skris 131957429Smarkm/* 132057429Smarkm * Returns a string from the packet data. The string is allocated using 132157429Smarkm * xmalloc; it is the responsibility of the calling program to free it when 132257429Smarkm * no longer needed. The length_ptr argument may be NULL, or point to an 132357429Smarkm * integer into which the length of the string is stored. 132457429Smarkm */ 132557429Smarkm 132692555Sdesvoid * 132776259Sgreenpacket_get_string(u_int *length_ptr) 132857429Smarkm{ 132957429Smarkm return buffer_get_string(&incoming_packet, length_ptr); 133057429Smarkm} 133157429Smarkm 133257429Smarkm/* 133357429Smarkm * Sends a diagnostic message from the server to the client. This message 133457429Smarkm * can be sent at any time (but not while constructing another message). The 133557429Smarkm * message is printed immediately, but only if the client is being executed 133657429Smarkm * in verbose mode. These messages are primarily intended to ease debugging 133757429Smarkm * authentication problems. The length of the formatted message must not 133857429Smarkm * exceed 1024 bytes. This will automatically call packet_write_wait. 133957429Smarkm */ 134057429Smarkm 134157429Smarkmvoid 134257429Smarkmpacket_send_debug(const char *fmt,...) 134357429Smarkm{ 134457429Smarkm char buf[1024]; 134557429Smarkm va_list args; 134657429Smarkm 134776259Sgreen if (compat20 && (datafellows & SSH_BUG_DEBUG)) 134876259Sgreen return; 134976259Sgreen 135057429Smarkm va_start(args, fmt); 135157429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 135257429Smarkm va_end(args); 135357429Smarkm 135460573Skris if (compat20) { 135560573Skris packet_start(SSH2_MSG_DEBUG); 135660573Skris packet_put_char(0); /* bool: always display */ 135760573Skris packet_put_cstring(buf); 135860573Skris packet_put_cstring(""); 135960573Skris } else { 136060573Skris packet_start(SSH_MSG_DEBUG); 136160573Skris packet_put_cstring(buf); 136260573Skris } 136357429Smarkm packet_send(); 136457429Smarkm packet_write_wait(); 136557429Smarkm} 136657429Smarkm 136757429Smarkm/* 136857429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the 136957429Smarkm * connection, and exits. This function never returns. The error message 137057429Smarkm * should not contain a newline. The length of the formatted message must 137157429Smarkm * not exceed 1024 bytes. 137257429Smarkm */ 137357429Smarkm 137457429Smarkmvoid 137557429Smarkmpacket_disconnect(const char *fmt,...) 137657429Smarkm{ 137757429Smarkm char buf[1024]; 137857429Smarkm va_list args; 137957429Smarkm static int disconnecting = 0; 1380106121Sdes 138157429Smarkm if (disconnecting) /* Guard against recursive invocations. */ 138257429Smarkm fatal("packet_disconnect called recursively."); 138357429Smarkm disconnecting = 1; 138457429Smarkm 138557429Smarkm /* 138657429Smarkm * Format the message. Note that the caller must make sure the 138757429Smarkm * message is of limited size. 138857429Smarkm */ 138957429Smarkm va_start(args, fmt); 139057429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 139157429Smarkm va_end(args); 139257429Smarkm 1393113908Sdes /* Display the error locally */ 1394124208Sdes logit("Disconnecting: %.100s", buf); 1395113908Sdes 139657429Smarkm /* Send the disconnect message to the other side, and wait for it to get sent. */ 139760573Skris if (compat20) { 139860573Skris packet_start(SSH2_MSG_DISCONNECT); 139960573Skris packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 140060573Skris packet_put_cstring(buf); 140160573Skris packet_put_cstring(""); 140260573Skris } else { 140360573Skris packet_start(SSH_MSG_DISCONNECT); 140492555Sdes packet_put_cstring(buf); 140560573Skris } 140657429Smarkm packet_send(); 140757429Smarkm packet_write_wait(); 140857429Smarkm 140957429Smarkm /* Stop listening for connections. */ 141092555Sdes channel_close_all(); 141157429Smarkm 141257429Smarkm /* Close the connection. */ 141357429Smarkm packet_close(); 1414126274Sdes cleanup_exit(255); 141557429Smarkm} 141657429Smarkm 141757429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */ 141857429Smarkm 141957429Smarkmvoid 142092555Sdespacket_write_poll(void) 142157429Smarkm{ 142257429Smarkm int len = buffer_len(&output); 1423106121Sdes 142457429Smarkm if (len > 0) { 142557429Smarkm len = write(connection_out, buffer_ptr(&output), len); 142657429Smarkm if (len <= 0) { 142757429Smarkm if (errno == EAGAIN) 142857429Smarkm return; 142957429Smarkm else 143057429Smarkm fatal("Write failed: %.100s", strerror(errno)); 143157429Smarkm } 143257429Smarkm buffer_consume(&output, len); 143357429Smarkm } 143457429Smarkm} 143557429Smarkm 143657429Smarkm/* 143757429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been 143857429Smarkm * written. 143957429Smarkm */ 144057429Smarkm 144157429Smarkmvoid 144292555Sdespacket_write_wait(void) 144357429Smarkm{ 144476259Sgreen fd_set *setp; 144576259Sgreen 1446162852Sdes setp = (fd_set *)xcalloc(howmany(connection_out + 1, NFDBITS), 144776259Sgreen sizeof(fd_mask)); 144857429Smarkm packet_write_poll(); 144957429Smarkm while (packet_have_data_to_write()) { 145076259Sgreen memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 145176259Sgreen sizeof(fd_mask)); 145276259Sgreen FD_SET(connection_out, setp); 145376259Sgreen while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && 145476259Sgreen (errno == EAGAIN || errno == EINTR)) 145576259Sgreen ; 145657429Smarkm packet_write_poll(); 145757429Smarkm } 145876259Sgreen xfree(setp); 145957429Smarkm} 146057429Smarkm 146157429Smarkm/* Returns true if there is buffered data to write to the connection. */ 146257429Smarkm 146357429Smarkmint 146492555Sdespacket_have_data_to_write(void) 146557429Smarkm{ 146657429Smarkm return buffer_len(&output) != 0; 146757429Smarkm} 146857429Smarkm 146957429Smarkm/* Returns true if there is not too much data to write to the connection. */ 147057429Smarkm 147157429Smarkmint 147292555Sdespacket_not_very_much_data_to_write(void) 147357429Smarkm{ 147457429Smarkm if (interactive_mode) 147557429Smarkm return buffer_len(&output) < 16384; 147657429Smarkm else 147757429Smarkm return buffer_len(&output) < 128 * 1024; 147857429Smarkm} 147957429Smarkm 1480124208Sdes 1481113908Sdesstatic void 1482113908Sdespacket_set_tos(int interactive) 1483113908Sdes{ 1484126274Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 1485113908Sdes int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT; 1486113908Sdes 1487113908Sdes if (!packet_connection_is_on_socket() || 1488113908Sdes !packet_connection_is_ipv4()) 1489113908Sdes return; 1490113908Sdes if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos, 1491113908Sdes sizeof(tos)) < 0) 1492113908Sdes error("setsockopt IP_TOS %d: %.100s:", 1493113908Sdes tos, strerror(errno)); 1494126274Sdes#endif 1495113908Sdes} 1496113908Sdes 149757429Smarkm/* Informs that the current session is interactive. Sets IP flags for that. */ 149857429Smarkm 149957429Smarkmvoid 150076259Sgreenpacket_set_interactive(int interactive) 150157429Smarkm{ 150276259Sgreen static int called = 0; 150357429Smarkm 150476259Sgreen if (called) 150576259Sgreen return; 150676259Sgreen called = 1; 150776259Sgreen 150857429Smarkm /* Record that we are in interactive mode. */ 150957429Smarkm interactive_mode = interactive; 151057429Smarkm 151157429Smarkm /* Only set socket options if using a socket. */ 151257429Smarkm if (!packet_connection_is_on_socket()) 1513116791Sdes return; 1514162852Sdes set_nodelay(connection_in); 1515113908Sdes packet_set_tos(interactive); 151657429Smarkm} 151757429Smarkm 151857429Smarkm/* Returns true if the current connection is interactive. */ 151957429Smarkm 152057429Smarkmint 152192555Sdespacket_is_interactive(void) 152257429Smarkm{ 152357429Smarkm return interactive_mode; 152457429Smarkm} 152557429Smarkm 1526137015Sdesint 1527124208Sdespacket_set_maxsize(u_int s) 152857429Smarkm{ 152957429Smarkm static int called = 0; 1530106121Sdes 153157429Smarkm if (called) { 1532124208Sdes logit("packet_set_maxsize: called twice: old %d new %d", 153360573Skris max_packet_size, s); 153457429Smarkm return -1; 153557429Smarkm } 153657429Smarkm if (s < 4 * 1024 || s > 1024 * 1024) { 1537124208Sdes logit("packet_set_maxsize: bad size %d", s); 153857429Smarkm return -1; 153957429Smarkm } 154092555Sdes called = 1; 154192555Sdes debug("packet_set_maxsize: setting to %d", s); 154257429Smarkm max_packet_size = s; 154357429Smarkm return s; 154457429Smarkm} 154576259Sgreen 154692555Sdes/* roundup current message to pad bytes */ 154792555Sdesvoid 154892555Sdespacket_add_padding(u_char pad) 154992555Sdes{ 155092555Sdes extra_pad = pad; 155192555Sdes} 155292555Sdes 155376259Sgreen/* 155476259Sgreen * 9.2. Ignored Data Message 155576259Sgreen * 155676259Sgreen * byte SSH_MSG_IGNORE 155776259Sgreen * string data 155876259Sgreen * 155976259Sgreen * All implementations MUST understand (and ignore) this message at any 156076259Sgreen * time (after receiving the protocol version). No implementation is 156176259Sgreen * required to send them. This message can be used as an additional 156276259Sgreen * protection measure against advanced traffic analysis techniques. 156376259Sgreen */ 156476259Sgreenvoid 156576259Sgreenpacket_send_ignore(int nbytes) 156676259Sgreen{ 1567137015Sdes u_int32_t rnd = 0; 156876259Sgreen int i; 156976259Sgreen 157076259Sgreen packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 157176259Sgreen packet_put_int(nbytes); 157292555Sdes for (i = 0; i < nbytes; i++) { 157376259Sgreen if (i % 4 == 0) 1574137015Sdes rnd = arc4random(); 1575162852Sdes packet_put_char((u_char)rnd & 0xff); 1576137015Sdes rnd >>= 8; 157776259Sgreen } 157876259Sgreen} 1579124208Sdes 1580137015Sdes#define MAX_PACKETS (1U<<31) 1581124208Sdesint 1582124208Sdespacket_need_rekeying(void) 1583124208Sdes{ 1584124208Sdes if (datafellows & SSH_BUG_NOREKEY) 1585124208Sdes return 0; 1586124208Sdes return 1587124208Sdes (p_send.packets > MAX_PACKETS) || 1588124208Sdes (p_read.packets > MAX_PACKETS) || 1589124208Sdes (max_blocks_out && (p_send.blocks > max_blocks_out)) || 1590124208Sdes (max_blocks_in && (p_read.blocks > max_blocks_in)); 1591124208Sdes} 1592124208Sdes 1593124208Sdesvoid 1594124208Sdespacket_set_rekey_limit(u_int32_t bytes) 1595124208Sdes{ 1596124208Sdes rekey_limit = bytes; 1597124208Sdes} 1598149749Sdes 1599149749Sdesvoid 1600149749Sdespacket_set_server(void) 1601149749Sdes{ 1602149749Sdes server_side = 1; 1603149749Sdes} 1604149749Sdes 1605149749Sdesvoid 1606149749Sdespacket_set_authenticated(void) 1607149749Sdes{ 1608149749Sdes after_authentication = 1; 1609149749Sdes} 1610