packet.c revision 126274
157429Smarkm/* 257429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 357429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 457429Smarkm * All rights reserved 557429Smarkm * This file contains code implementing the packet protocol and communication 657429Smarkm * with the other side. This same code is used both on client and server side. 760573Skris * 865668Skris * As far as I am concerned, the code I have written for this software 965668Skris * can be used freely for any purpose. Any derived versions of this 1065668Skris * software must be clearly marked as such, and if the derived work is 1165668Skris * incompatible with the protocol description in the RFC file, it must be 1265668Skris * called by a name other than "ssh" or "Secure Shell". 1365668Skris * 1465668Skris * 1560573Skris * SSH2 packet format added by Markus Friedl. 1692555Sdes * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 1760573Skris * 1865668Skris * Redistribution and use in source and binary forms, with or without 1965668Skris * modification, are permitted provided that the following conditions 2065668Skris * are met: 2165668Skris * 1. Redistributions of source code must retain the above copyright 2265668Skris * notice, this list of conditions and the following disclaimer. 2365668Skris * 2. Redistributions in binary form must reproduce the above copyright 2465668Skris * notice, this list of conditions and the following disclaimer in the 2565668Skris * documentation and/or other materials provided with the distribution. 2665668Skris * 2765668Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2865668Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2965668Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 3065668Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 3165668Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 3265668Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3365668Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3465668Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3565668Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3665668Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3757429Smarkm */ 3857429Smarkm 3957429Smarkm#include "includes.h" 40126274SdesRCSID("$OpenBSD: packet.c,v 1.112 2003/09/23 20:17:11 markus Exp $"); 4157429Smarkm 42124208Sdes#include "openbsd-compat/sys-queue.h" 43124208Sdes 4457429Smarkm#include "xmalloc.h" 4557429Smarkm#include "buffer.h" 4657429Smarkm#include "packet.h" 4757429Smarkm#include "bufaux.h" 4857429Smarkm#include "crc32.h" 4957429Smarkm#include "getput.h" 5057429Smarkm 5157429Smarkm#include "compress.h" 5257429Smarkm#include "deattack.h" 5360573Skris#include "channels.h" 5457429Smarkm 5560573Skris#include "compat.h" 5676259Sgreen#include "ssh1.h" 5760573Skris#include "ssh2.h" 5860573Skris 5969587Sgreen#include "cipher.h" 6060573Skris#include "kex.h" 6176259Sgreen#include "mac.h" 6276259Sgreen#include "log.h" 6376259Sgreen#include "canohost.h" 6492555Sdes#include "misc.h" 6598675Sdes#include "ssh.h" 6660573Skris 6760573Skris#ifdef PACKET_DEBUG 6860573Skris#define DBG(x) x 6960573Skris#else 7060573Skris#define DBG(x) 7160573Skris#endif 7260573Skris 7357429Smarkm/* 7457429Smarkm * This variable contains the file descriptors used for communicating with 7557429Smarkm * the other side. connection_in is used for reading; connection_out for 7657429Smarkm * writing. These can be the same descriptor, in which case it is assumed to 7757429Smarkm * be a socket. 7857429Smarkm */ 7957429Smarkmstatic int connection_in = -1; 8057429Smarkmstatic int connection_out = -1; 8157429Smarkm 8257429Smarkm/* Protocol flags for the remote side. */ 8376259Sgreenstatic u_int remote_protocol_flags = 0; 8457429Smarkm 8557429Smarkm/* Encryption context for receiving data. This is only used for decryption. */ 8657429Smarkmstatic CipherContext receive_context; 8757429Smarkm 8857429Smarkm/* Encryption context for sending data. This is only used for encryption. */ 8957429Smarkmstatic CipherContext send_context; 9057429Smarkm 9157429Smarkm/* Buffer for raw input data from the socket. */ 9298675SdesBuffer input; 9357429Smarkm 9457429Smarkm/* Buffer for raw output data going to the socket. */ 9598675SdesBuffer output; 9657429Smarkm 9757429Smarkm/* Buffer for the partial outgoing packet being constructed. */ 9857429Smarkmstatic Buffer outgoing_packet; 9957429Smarkm 10057429Smarkm/* Buffer for the incoming packet currently being processed. */ 10157429Smarkmstatic Buffer incoming_packet; 10257429Smarkm 10357429Smarkm/* Scratch buffer for packet compression/decompression. */ 10457429Smarkmstatic Buffer compression_buffer; 10576259Sgreenstatic int compression_buffer_ready = 0; 10657429Smarkm 10757429Smarkm/* Flag indicating whether packet compression/decompression is enabled. */ 10857429Smarkmstatic int packet_compression = 0; 10957429Smarkm 11057429Smarkm/* default maximum packet size */ 111124208Sdesu_int max_packet_size = 32768; 11257429Smarkm 11357429Smarkm/* Flag indicating whether this module has been initialized. */ 11457429Smarkmstatic int initialized = 0; 11557429Smarkm 11657429Smarkm/* Set to true if the connection is interactive. */ 11757429Smarkmstatic int interactive_mode = 0; 11857429Smarkm 11960573Skris/* Session key information for Encryption and MAC */ 12076259SgreenNewkeys *newkeys[MODE_MAX]; 121124208Sdesstatic struct packet_state { 122124208Sdes u_int32_t seqnr; 123124208Sdes u_int32_t packets; 124124208Sdes u_int64_t blocks; 125124208Sdes} p_read, p_send; 12660573Skris 127124208Sdesstatic u_int64_t max_blocks_in, max_blocks_out; 128124208Sdesstatic u_int32_t rekey_limit; 129124208Sdes 13098675Sdes/* Session key for protocol v1 */ 13198675Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 13298675Sdesstatic u_int ssh1_keylen; 13398675Sdes 13492555Sdes/* roundup current message to extra_pad bytes */ 13592555Sdesstatic u_char extra_pad = 0; 13660573Skris 137124208Sdesstruct packet { 138124208Sdes TAILQ_ENTRY(packet) next; 139124208Sdes u_char type; 140124208Sdes Buffer payload; 141124208Sdes}; 142124208SdesTAILQ_HEAD(, packet) outgoing; 143124208Sdes 14457429Smarkm/* 14557429Smarkm * Sets the descriptors used for communication. Disables encryption until 14657429Smarkm * packet_set_encryption_key is called. 14757429Smarkm */ 14857429Smarkmvoid 14957429Smarkmpacket_set_connection(int fd_in, int fd_out) 15057429Smarkm{ 15169587Sgreen Cipher *none = cipher_by_name("none"); 152106121Sdes 15369587Sgreen if (none == NULL) 15469587Sgreen fatal("packet_set_connection: cannot load cipher 'none'"); 15557429Smarkm connection_in = fd_in; 15657429Smarkm connection_out = fd_out; 15792555Sdes cipher_init(&send_context, none, "", 0, NULL, 0, CIPHER_ENCRYPT); 15892555Sdes cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT); 15992555Sdes newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; 16057429Smarkm if (!initialized) { 16157429Smarkm initialized = 1; 16257429Smarkm buffer_init(&input); 16357429Smarkm buffer_init(&output); 16457429Smarkm buffer_init(&outgoing_packet); 16557429Smarkm buffer_init(&incoming_packet); 166124208Sdes TAILQ_INIT(&outgoing); 16757429Smarkm } 16857429Smarkm} 16957429Smarkm 17057429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */ 17157429Smarkm 17257429Smarkmint 17392555Sdespacket_connection_is_on_socket(void) 17457429Smarkm{ 17557429Smarkm struct sockaddr_storage from, to; 17657429Smarkm socklen_t fromlen, tolen; 17757429Smarkm 17857429Smarkm /* filedescriptors in and out are the same, so it's a socket */ 17957429Smarkm if (connection_in == connection_out) 18057429Smarkm return 1; 18157429Smarkm fromlen = sizeof(from); 18257429Smarkm memset(&from, 0, sizeof(from)); 18357429Smarkm if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0) 18457429Smarkm return 0; 18557429Smarkm tolen = sizeof(to); 18657429Smarkm memset(&to, 0, sizeof(to)); 18757429Smarkm if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0) 18857429Smarkm return 0; 18957429Smarkm if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) 19057429Smarkm return 0; 19157429Smarkm if (from.ss_family != AF_INET && from.ss_family != AF_INET6) 19257429Smarkm return 0; 19357429Smarkm return 1; 19457429Smarkm} 19557429Smarkm 19698675Sdes/* 19798675Sdes * Exports an IV from the CipherContext required to export the key 19898675Sdes * state back from the unprivileged child to the privileged parent 19998675Sdes * process. 20098675Sdes */ 20198675Sdes 20298675Sdesvoid 20398675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len) 20498675Sdes{ 20598675Sdes CipherContext *cc; 20698675Sdes 20798675Sdes if (mode == MODE_OUT) 20898675Sdes cc = &send_context; 20998675Sdes else 21098675Sdes cc = &receive_context; 21198675Sdes 21298675Sdes cipher_get_keyiv(cc, iv, len); 21398675Sdes} 21498675Sdes 21598675Sdesint 21698675Sdespacket_get_keycontext(int mode, u_char *dat) 21798675Sdes{ 21898675Sdes CipherContext *cc; 21998675Sdes 22098675Sdes if (mode == MODE_OUT) 22198675Sdes cc = &send_context; 22298675Sdes else 22398675Sdes cc = &receive_context; 22498675Sdes 22598675Sdes return (cipher_get_keycontext(cc, dat)); 22698675Sdes} 22798675Sdes 22898675Sdesvoid 22998675Sdespacket_set_keycontext(int mode, u_char *dat) 23098675Sdes{ 23198675Sdes CipherContext *cc; 23298675Sdes 23398675Sdes if (mode == MODE_OUT) 23498675Sdes cc = &send_context; 23598675Sdes else 23698675Sdes cc = &receive_context; 23798675Sdes 23898675Sdes cipher_set_keycontext(cc, dat); 23998675Sdes} 24098675Sdes 24198675Sdesint 24298675Sdespacket_get_keyiv_len(int mode) 24398675Sdes{ 24498675Sdes CipherContext *cc; 24598675Sdes 24698675Sdes if (mode == MODE_OUT) 24798675Sdes cc = &send_context; 24898675Sdes else 24998675Sdes cc = &receive_context; 25098675Sdes 25198675Sdes return (cipher_get_keyiv_len(cc)); 25298675Sdes} 25398675Sdesvoid 25498675Sdespacket_set_iv(int mode, u_char *dat) 25598675Sdes{ 25698675Sdes CipherContext *cc; 25798675Sdes 25898675Sdes if (mode == MODE_OUT) 25998675Sdes cc = &send_context; 26098675Sdes else 26198675Sdes cc = &receive_context; 26298675Sdes 26398675Sdes cipher_set_keyiv(cc, dat); 26498675Sdes} 26598675Sdesint 266124208Sdespacket_get_ssh1_cipher(void) 26798675Sdes{ 26898675Sdes return (cipher_get_number(receive_context.cipher)); 26998675Sdes} 27098675Sdes 271124208Sdesvoid 272124208Sdespacket_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, u_int32_t *packets) 273124208Sdes{ 274124208Sdes struct packet_state *state; 27598675Sdes 276124208Sdes state = (mode == MODE_IN) ? &p_read : &p_send; 277124208Sdes *seqnr = state->seqnr; 278124208Sdes *blocks = state->blocks; 279124208Sdes *packets = state->packets; 28098675Sdes} 28198675Sdes 28298675Sdesvoid 283124208Sdespacket_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets) 28498675Sdes{ 285124208Sdes struct packet_state *state; 286124208Sdes 287124208Sdes state = (mode == MODE_IN) ? &p_read : &p_send; 288124208Sdes state->seqnr = seqnr; 289124208Sdes state->blocks = blocks; 290124208Sdes state->packets = packets; 29198675Sdes} 29298675Sdes 29357429Smarkm/* returns 1 if connection is via ipv4 */ 29457429Smarkm 29557429Smarkmint 29692555Sdespacket_connection_is_ipv4(void) 29757429Smarkm{ 29857429Smarkm struct sockaddr_storage to; 29957429Smarkm socklen_t tolen = sizeof(to); 30057429Smarkm 30157429Smarkm memset(&to, 0, sizeof(to)); 30257429Smarkm if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) 30357429Smarkm return 0; 30498937Sdes if (to.ss_family == AF_INET) 30598937Sdes return 1; 30698937Sdes#ifdef IPV4_IN_IPV6 307126274Sdes if (to.ss_family == AF_INET6 && 30898937Sdes IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) 30998937Sdes return 1; 31098937Sdes#endif 31198937Sdes return 0; 31257429Smarkm} 31357429Smarkm 31457429Smarkm/* Sets the connection into non-blocking mode. */ 31557429Smarkm 31657429Smarkmvoid 31792555Sdespacket_set_nonblocking(void) 31857429Smarkm{ 31957429Smarkm /* Set the socket into non-blocking mode. */ 32057429Smarkm if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0) 32157429Smarkm error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 32257429Smarkm 32357429Smarkm if (connection_out != connection_in) { 32457429Smarkm if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0) 32557429Smarkm error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 32657429Smarkm } 32757429Smarkm} 32857429Smarkm 32957429Smarkm/* Returns the socket used for reading. */ 33057429Smarkm 33157429Smarkmint 33292555Sdespacket_get_connection_in(void) 33357429Smarkm{ 33457429Smarkm return connection_in; 33557429Smarkm} 33657429Smarkm 33757429Smarkm/* Returns the descriptor used for writing. */ 33857429Smarkm 33957429Smarkmint 34092555Sdespacket_get_connection_out(void) 34157429Smarkm{ 34257429Smarkm return connection_out; 34357429Smarkm} 34457429Smarkm 34557429Smarkm/* Closes the connection and clears and frees internal data structures. */ 34657429Smarkm 34757429Smarkmvoid 34892555Sdespacket_close(void) 34957429Smarkm{ 35057429Smarkm if (!initialized) 35157429Smarkm return; 35257429Smarkm initialized = 0; 35357429Smarkm if (connection_in == connection_out) { 35457429Smarkm shutdown(connection_out, SHUT_RDWR); 35557429Smarkm close(connection_out); 35657429Smarkm } else { 35757429Smarkm close(connection_in); 35857429Smarkm close(connection_out); 35957429Smarkm } 36057429Smarkm buffer_free(&input); 36157429Smarkm buffer_free(&output); 36257429Smarkm buffer_free(&outgoing_packet); 36357429Smarkm buffer_free(&incoming_packet); 36476259Sgreen if (compression_buffer_ready) { 36557429Smarkm buffer_free(&compression_buffer); 36657429Smarkm buffer_compress_uninit(); 36757429Smarkm } 36892555Sdes cipher_cleanup(&send_context); 36992555Sdes cipher_cleanup(&receive_context); 37057429Smarkm} 37157429Smarkm 37257429Smarkm/* Sets remote side protocol flags. */ 37357429Smarkm 37457429Smarkmvoid 37576259Sgreenpacket_set_protocol_flags(u_int protocol_flags) 37657429Smarkm{ 37757429Smarkm remote_protocol_flags = protocol_flags; 37857429Smarkm} 37957429Smarkm 38057429Smarkm/* Returns the remote protocol flags set earlier by the above function. */ 38157429Smarkm 38276259Sgreenu_int 38392555Sdespacket_get_protocol_flags(void) 38457429Smarkm{ 38557429Smarkm return remote_protocol_flags; 38657429Smarkm} 38757429Smarkm 38857429Smarkm/* 38957429Smarkm * Starts packet compression from the next packet on in both directions. 39057429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. 39157429Smarkm */ 39257429Smarkm 39392555Sdesstatic void 39492555Sdespacket_init_compression(void) 39576259Sgreen{ 39676259Sgreen if (compression_buffer_ready == 1) 39776259Sgreen return; 39876259Sgreen compression_buffer_ready = 1; 39976259Sgreen buffer_init(&compression_buffer); 40076259Sgreen} 40176259Sgreen 40276259Sgreenvoid 40357429Smarkmpacket_start_compression(int level) 40457429Smarkm{ 40592555Sdes if (packet_compression && !compat20) 40657429Smarkm fatal("Compression already enabled."); 40757429Smarkm packet_compression = 1; 40876259Sgreen packet_init_compression(); 40976259Sgreen buffer_compress_init_send(level); 41076259Sgreen buffer_compress_init_recv(); 41157429Smarkm} 41257429Smarkm 41357429Smarkm/* 41457429Smarkm * Causes any further packets to be encrypted using the given key. The same 41557429Smarkm * key is used for both sending and reception. However, both directions are 41657429Smarkm * encrypted independently of each other. 41757429Smarkm */ 41898675Sdes 41957429Smarkmvoid 42076259Sgreenpacket_set_encryption_key(const u_char *key, u_int keylen, 42169587Sgreen int number) 42257429Smarkm{ 42369587Sgreen Cipher *cipher = cipher_by_number(number); 424106121Sdes 42569587Sgreen if (cipher == NULL) 42669587Sgreen fatal("packet_set_encryption_key: unknown cipher number %d", number); 42760573Skris if (keylen < 20) 42869587Sgreen fatal("packet_set_encryption_key: keylen too small: %d", keylen); 42998675Sdes if (keylen > SSH_SESSION_KEY_LENGTH) 43098675Sdes fatal("packet_set_encryption_key: keylen too big: %d", keylen); 43198675Sdes memcpy(ssh1_key, key, keylen); 43298675Sdes ssh1_keylen = keylen; 43392555Sdes cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); 43492555Sdes cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); 43557429Smarkm} 43657429Smarkm 43798675Sdesu_int 43898675Sdespacket_get_encryption_key(u_char *key) 43998675Sdes{ 44098675Sdes if (key == NULL) 44198675Sdes return (ssh1_keylen); 44298675Sdes memcpy(key, ssh1_key, ssh1_keylen); 44398675Sdes return (ssh1_keylen); 44498675Sdes} 44598675Sdes 44692555Sdes/* Start constructing a packet to send. */ 44757429Smarkmvoid 44892555Sdespacket_start(u_char type) 44957429Smarkm{ 45092555Sdes u_char buf[9]; 45192555Sdes int len; 45257429Smarkm 45392555Sdes DBG(debug("packet_start[%d]", type)); 45492555Sdes len = compat20 ? 6 : 9; 45592555Sdes memset(buf, 0, len - 1); 45692555Sdes buf[len - 1] = type; 45757429Smarkm buffer_clear(&outgoing_packet); 45892555Sdes buffer_append(&outgoing_packet, buf, len); 45957429Smarkm} 46057429Smarkm 46192555Sdes/* Append payload. */ 46260573Skrisvoid 46357429Smarkmpacket_put_char(int value) 46457429Smarkm{ 46557429Smarkm char ch = value; 466106121Sdes 46757429Smarkm buffer_append(&outgoing_packet, &ch, 1); 46857429Smarkm} 46957429Smarkmvoid 47076259Sgreenpacket_put_int(u_int value) 47157429Smarkm{ 47257429Smarkm buffer_put_int(&outgoing_packet, value); 47357429Smarkm} 47457429Smarkmvoid 47592555Sdespacket_put_string(const void *buf, u_int len) 47657429Smarkm{ 47757429Smarkm buffer_put_string(&outgoing_packet, buf, len); 47857429Smarkm} 47960573Skrisvoid 48060573Skrispacket_put_cstring(const char *str) 48160573Skris{ 48292555Sdes buffer_put_cstring(&outgoing_packet, str); 48360573Skris} 48460573Skrisvoid 48592555Sdespacket_put_raw(const void *buf, u_int len) 48660573Skris{ 48760573Skris buffer_append(&outgoing_packet, buf, len); 48860573Skris} 48957429Smarkmvoid 49057429Smarkmpacket_put_bignum(BIGNUM * value) 49157429Smarkm{ 49257429Smarkm buffer_put_bignum(&outgoing_packet, value); 49357429Smarkm} 49460573Skrisvoid 49560573Skrispacket_put_bignum2(BIGNUM * value) 49660573Skris{ 49760573Skris buffer_put_bignum2(&outgoing_packet, value); 49860573Skris} 49957429Smarkm 50057429Smarkm/* 50157429Smarkm * Finalizes and sends the packet. If the encryption key has been set, 50257429Smarkm * encrypts the packet before sending. 50357429Smarkm */ 50457429Smarkm 50592555Sdesstatic void 50676259Sgreenpacket_send1(void) 50757429Smarkm{ 50892555Sdes u_char buf[8], *cp; 50957429Smarkm int i, padding, len; 51076259Sgreen u_int checksum; 51157429Smarkm u_int32_t rand = 0; 51257429Smarkm 51357429Smarkm /* 51457429Smarkm * If using packet compression, compress the payload of the outgoing 51557429Smarkm * packet. 51657429Smarkm */ 51757429Smarkm if (packet_compression) { 51857429Smarkm buffer_clear(&compression_buffer); 51957429Smarkm /* Skip padding. */ 52057429Smarkm buffer_consume(&outgoing_packet, 8); 52157429Smarkm /* padding */ 52257429Smarkm buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); 52357429Smarkm buffer_compress(&outgoing_packet, &compression_buffer); 52457429Smarkm buffer_clear(&outgoing_packet); 52557429Smarkm buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 52692555Sdes buffer_len(&compression_buffer)); 52757429Smarkm } 52857429Smarkm /* Compute packet length without padding (add checksum, remove padding). */ 52957429Smarkm len = buffer_len(&outgoing_packet) + 4 - 8; 53057429Smarkm 53160573Skris /* Insert padding. Initialized to zero in packet_start1() */ 53257429Smarkm padding = 8 - len % 8; 53392555Sdes if (!send_context.plaintext) { 53457429Smarkm cp = buffer_ptr(&outgoing_packet); 53557429Smarkm for (i = 0; i < padding; i++) { 53657429Smarkm if (i % 4 == 0) 53757429Smarkm rand = arc4random(); 53857429Smarkm cp[7 - i] = rand & 0xff; 53957429Smarkm rand >>= 8; 54057429Smarkm } 54157429Smarkm } 54257429Smarkm buffer_consume(&outgoing_packet, 8 - padding); 54357429Smarkm 54457429Smarkm /* Add check bytes. */ 54592555Sdes checksum = ssh_crc32(buffer_ptr(&outgoing_packet), 54665668Skris buffer_len(&outgoing_packet)); 54757429Smarkm PUT_32BIT(buf, checksum); 54857429Smarkm buffer_append(&outgoing_packet, buf, 4); 54957429Smarkm 55057429Smarkm#ifdef PACKET_DEBUG 55157429Smarkm fprintf(stderr, "packet_send plain: "); 55257429Smarkm buffer_dump(&outgoing_packet); 55357429Smarkm#endif 55457429Smarkm 55557429Smarkm /* Append to output. */ 55657429Smarkm PUT_32BIT(buf, len); 55757429Smarkm buffer_append(&output, buf, 4); 55892555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 55992555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 56092555Sdes buffer_len(&outgoing_packet)); 56157429Smarkm 56257429Smarkm#ifdef PACKET_DEBUG 56357429Smarkm fprintf(stderr, "encrypted: "); 56457429Smarkm buffer_dump(&output); 56557429Smarkm#endif 56657429Smarkm 56757429Smarkm buffer_clear(&outgoing_packet); 56857429Smarkm 56957429Smarkm /* 57057429Smarkm * Note that the packet is now only buffered in output. It won\'t be 57157429Smarkm * actually sent until packet_write_wait or packet_write_poll is 57257429Smarkm * called. 57357429Smarkm */ 57457429Smarkm} 57557429Smarkm 57698675Sdesvoid 57776259Sgreenset_newkeys(int mode) 57876259Sgreen{ 57976259Sgreen Enc *enc; 58076259Sgreen Mac *mac; 58176259Sgreen Comp *comp; 58276259Sgreen CipherContext *cc; 583124208Sdes u_int64_t *max_blocks; 58492555Sdes int encrypt; 58576259Sgreen 586113908Sdes debug2("set_newkeys: mode %d", mode); 58776259Sgreen 58892555Sdes if (mode == MODE_OUT) { 58992555Sdes cc = &send_context; 59092555Sdes encrypt = CIPHER_ENCRYPT; 591124208Sdes p_send.packets = p_send.blocks = 0; 592124208Sdes max_blocks = &max_blocks_out; 59392555Sdes } else { 59492555Sdes cc = &receive_context; 59592555Sdes encrypt = CIPHER_DECRYPT; 596124208Sdes p_read.packets = p_read.blocks = 0; 597124208Sdes max_blocks = &max_blocks_in; 59892555Sdes } 59976259Sgreen if (newkeys[mode] != NULL) { 600113908Sdes debug("set_newkeys: rekeying"); 60192555Sdes cipher_cleanup(cc); 60276259Sgreen enc = &newkeys[mode]->enc; 60376259Sgreen mac = &newkeys[mode]->mac; 60476259Sgreen comp = &newkeys[mode]->comp; 60576259Sgreen memset(mac->key, 0, mac->key_len); 60676259Sgreen xfree(enc->name); 60776259Sgreen xfree(enc->iv); 60876259Sgreen xfree(enc->key); 60976259Sgreen xfree(mac->name); 61076259Sgreen xfree(mac->key); 61176259Sgreen xfree(comp->name); 61276259Sgreen xfree(newkeys[mode]); 61376259Sgreen } 61476259Sgreen newkeys[mode] = kex_get_newkeys(mode); 61576259Sgreen if (newkeys[mode] == NULL) 61676259Sgreen fatal("newkeys: no keys for mode %d", mode); 61776259Sgreen enc = &newkeys[mode]->enc; 61876259Sgreen mac = &newkeys[mode]->mac; 61976259Sgreen comp = &newkeys[mode]->comp; 62076259Sgreen if (mac->md != NULL) 62176259Sgreen mac->enabled = 1; 62276259Sgreen DBG(debug("cipher_init_context: %d", mode)); 62392555Sdes cipher_init(cc, enc->cipher, enc->key, enc->key_len, 62492555Sdes enc->iv, enc->block_size, encrypt); 62598675Sdes /* Deleting the keys does not gain extra security */ 62698675Sdes /* memset(enc->iv, 0, enc->block_size); 62798675Sdes memset(enc->key, 0, enc->key_len); */ 62876259Sgreen if (comp->type != 0 && comp->enabled == 0) { 62976259Sgreen packet_init_compression(); 63076259Sgreen if (mode == MODE_OUT) 63176259Sgreen buffer_compress_init_send(6); 63276259Sgreen else 63376259Sgreen buffer_compress_init_recv(); 63476259Sgreen comp->enabled = 1; 63576259Sgreen } 636124208Sdes /* 637124208Sdes * The 2^(blocksize*2) limit is too expensive for 3DES, 638124208Sdes * blowfish, etc, so enforce a 1GB limit for small blocksizes. 639124208Sdes */ 640124208Sdes if (enc->block_size >= 16) 641124208Sdes *max_blocks = (u_int64_t)1 << (enc->block_size*2); 642124208Sdes else 643124208Sdes *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; 644124208Sdes if (rekey_limit) 645124208Sdes *max_blocks = MIN(*max_blocks, rekey_limit / enc->block_size); 64676259Sgreen} 64776259Sgreen 64857429Smarkm/* 64960573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 65060573Skris */ 65192555Sdesstatic void 652124208Sdespacket_send2_wrapped(void) 65360573Skris{ 65492555Sdes u_char type, *cp, *macbuf = NULL; 65592555Sdes u_char padlen, pad; 65676259Sgreen u_int packet_length = 0; 65792555Sdes u_int i, len; 65860573Skris u_int32_t rand = 0; 65960573Skris Enc *enc = NULL; 66060573Skris Mac *mac = NULL; 66160573Skris Comp *comp = NULL; 66260573Skris int block_size; 66360573Skris 66476259Sgreen if (newkeys[MODE_OUT] != NULL) { 66576259Sgreen enc = &newkeys[MODE_OUT]->enc; 66676259Sgreen mac = &newkeys[MODE_OUT]->mac; 66776259Sgreen comp = &newkeys[MODE_OUT]->comp; 66860573Skris } 66992555Sdes block_size = enc ? enc->block_size : 8; 67060573Skris 67160573Skris cp = buffer_ptr(&outgoing_packet); 67292555Sdes type = cp[5]; 67360573Skris 67460573Skris#ifdef PACKET_DEBUG 67560573Skris fprintf(stderr, "plain: "); 67660573Skris buffer_dump(&outgoing_packet); 67760573Skris#endif 67860573Skris 67960573Skris if (comp && comp->enabled) { 68060573Skris len = buffer_len(&outgoing_packet); 68160573Skris /* skip header, compress only payload */ 68260573Skris buffer_consume(&outgoing_packet, 5); 68360573Skris buffer_clear(&compression_buffer); 68460573Skris buffer_compress(&outgoing_packet, &compression_buffer); 68560573Skris buffer_clear(&outgoing_packet); 68660573Skris buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); 68760573Skris buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 68860573Skris buffer_len(&compression_buffer)); 68960573Skris DBG(debug("compression: raw %d compressed %d", len, 69060573Skris buffer_len(&outgoing_packet))); 69160573Skris } 69260573Skris 69360573Skris /* sizeof (packet_len + pad_len + payload) */ 69460573Skris len = buffer_len(&outgoing_packet); 69560573Skris 69660573Skris /* 69760573Skris * calc size of padding, alloc space, get random data, 69860573Skris * minimum padding is 4 bytes 69960573Skris */ 70060573Skris padlen = block_size - (len % block_size); 70160573Skris if (padlen < 4) 70260573Skris padlen += block_size; 70392555Sdes if (extra_pad) { 70492555Sdes /* will wrap if extra_pad+padlen > 255 */ 70592555Sdes extra_pad = roundup(extra_pad, block_size); 70692555Sdes pad = extra_pad - ((len + padlen) % extra_pad); 70798675Sdes debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 70892555Sdes pad, len, padlen, extra_pad); 70992555Sdes padlen += pad; 71092555Sdes extra_pad = 0; 71192555Sdes } 71292555Sdes cp = buffer_append_space(&outgoing_packet, padlen); 71392555Sdes if (enc && !send_context.plaintext) { 71460573Skris /* random padding */ 71560573Skris for (i = 0; i < padlen; i++) { 71660573Skris if (i % 4 == 0) 71760573Skris rand = arc4random(); 71860573Skris cp[i] = rand & 0xff; 71976259Sgreen rand >>= 8; 72060573Skris } 72160573Skris } else { 72260573Skris /* clear padding */ 72360573Skris memset(cp, 0, padlen); 72460573Skris } 72560573Skris /* packet_length includes payload, padding and padding length field */ 72660573Skris packet_length = buffer_len(&outgoing_packet) - 4; 72760573Skris cp = buffer_ptr(&outgoing_packet); 72860573Skris PUT_32BIT(cp, packet_length); 72992555Sdes cp[4] = padlen; 73060573Skris DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); 73160573Skris 73260573Skris /* compute MAC over seqnr and packet(length fields, payload, padding) */ 73360573Skris if (mac && mac->enabled) { 734124208Sdes macbuf = mac_compute(mac, p_send.seqnr, 73592555Sdes buffer_ptr(&outgoing_packet), 73676259Sgreen buffer_len(&outgoing_packet)); 737124208Sdes DBG(debug("done calc MAC out #%d", p_send.seqnr)); 73860573Skris } 73960573Skris /* encrypt packet and append to output buffer. */ 74092555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 74192555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 74260573Skris buffer_len(&outgoing_packet)); 74360573Skris /* append unencrypted MAC */ 74460573Skris if (mac && mac->enabled) 74560573Skris buffer_append(&output, (char *)macbuf, mac->mac_len); 74660573Skris#ifdef PACKET_DEBUG 74760573Skris fprintf(stderr, "encrypted: "); 74860573Skris buffer_dump(&output); 74960573Skris#endif 75060573Skris /* increment sequence number for outgoing packets */ 751124208Sdes if (++p_send.seqnr == 0) 752124208Sdes logit("outgoing seqnr wraps around"); 753124208Sdes if (++p_send.packets == 0) 754124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 755124208Sdes fatal("XXX too many packets with same key"); 756124208Sdes p_send.blocks += (packet_length + 4) / block_size; 75760573Skris buffer_clear(&outgoing_packet); 75860573Skris 75976259Sgreen if (type == SSH2_MSG_NEWKEYS) 76076259Sgreen set_newkeys(MODE_OUT); 76160573Skris} 76260573Skris 763124208Sdesstatic void 764124208Sdespacket_send2(void) 765124208Sdes{ 766124208Sdes static int rekeying = 0; 767124208Sdes struct packet *p; 768124208Sdes u_char type, *cp; 769124208Sdes 770124208Sdes cp = buffer_ptr(&outgoing_packet); 771124208Sdes type = cp[5]; 772124208Sdes 773124208Sdes /* during rekeying we can only send key exchange messages */ 774124208Sdes if (rekeying) { 775124208Sdes if (!((type >= SSH2_MSG_TRANSPORT_MIN) && 776124208Sdes (type <= SSH2_MSG_TRANSPORT_MAX))) { 777124208Sdes debug("enqueue packet: %u", type); 778124208Sdes p = xmalloc(sizeof(*p)); 779124208Sdes p->type = type; 780124208Sdes memcpy(&p->payload, &outgoing_packet, sizeof(Buffer)); 781124208Sdes buffer_init(&outgoing_packet); 782124208Sdes TAILQ_INSERT_TAIL(&outgoing, p, next); 783124208Sdes return; 784124208Sdes } 785124208Sdes } 786124208Sdes 787124208Sdes /* rekeying starts with sending KEXINIT */ 788124208Sdes if (type == SSH2_MSG_KEXINIT) 789124208Sdes rekeying = 1; 790124208Sdes 791124208Sdes packet_send2_wrapped(); 792124208Sdes 793124208Sdes /* after a NEWKEYS message we can send the complete queue */ 794124208Sdes if (type == SSH2_MSG_NEWKEYS) { 795124208Sdes rekeying = 0; 796124208Sdes while ((p = TAILQ_FIRST(&outgoing))) { 797124208Sdes type = p->type; 798124208Sdes debug("dequeue packet: %u", type); 799124208Sdes buffer_free(&outgoing_packet); 800124208Sdes memcpy(&outgoing_packet, &p->payload, 801124208Sdes sizeof(Buffer)); 802124208Sdes TAILQ_REMOVE(&outgoing, p, next); 803124208Sdes xfree(p); 804124208Sdes packet_send2_wrapped(); 805124208Sdes } 806124208Sdes } 807124208Sdes} 808124208Sdes 80960573Skrisvoid 81092555Sdespacket_send(void) 81160573Skris{ 81292555Sdes if (compat20) 81360573Skris packet_send2(); 81460573Skris else 81560573Skris packet_send1(); 81660573Skris DBG(debug("packet_send done")); 81760573Skris} 81860573Skris 81960573Skris/* 82057429Smarkm * Waits until a packet has been received, and returns its type. Note that 82157429Smarkm * no other data is processed until this returns, so this function should not 82257429Smarkm * be used during the interactive session. 82357429Smarkm */ 82457429Smarkm 82557429Smarkmint 82692555Sdespacket_read_seqnr(u_int32_t *seqnr_p) 82757429Smarkm{ 82857429Smarkm int type, len; 82976259Sgreen fd_set *setp; 83057429Smarkm char buf[8192]; 83160573Skris DBG(debug("packet_read()")); 83257429Smarkm 83376259Sgreen setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) * 83476259Sgreen sizeof(fd_mask)); 83576259Sgreen 83657429Smarkm /* Since we are blocking, ensure that all written packets have been sent. */ 83757429Smarkm packet_write_wait(); 83857429Smarkm 83957429Smarkm /* Stay in the loop until we have received a complete packet. */ 84057429Smarkm for (;;) { 84157429Smarkm /* Try to read a packet from the buffer. */ 84292555Sdes type = packet_read_poll_seqnr(seqnr_p); 84392555Sdes if (!compat20 && ( 84460573Skris type == SSH_SMSG_SUCCESS 84557429Smarkm || type == SSH_SMSG_FAILURE 84657429Smarkm || type == SSH_CMSG_EOF 84760573Skris || type == SSH_CMSG_EXIT_CONFIRMATION)) 84892555Sdes packet_check_eom(); 84957429Smarkm /* If we got a packet, return it. */ 85076259Sgreen if (type != SSH_MSG_NONE) { 85176259Sgreen xfree(setp); 85257429Smarkm return type; 85376259Sgreen } 85457429Smarkm /* 85557429Smarkm * Otherwise, wait for some data to arrive, add it to the 85657429Smarkm * buffer, and try again. 85757429Smarkm */ 85876259Sgreen memset(setp, 0, howmany(connection_in + 1, NFDBITS) * 85976259Sgreen sizeof(fd_mask)); 86076259Sgreen FD_SET(connection_in, setp); 86157429Smarkm 86257429Smarkm /* Wait for some data to arrive. */ 86376259Sgreen while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && 86476259Sgreen (errno == EAGAIN || errno == EINTR)) 86576259Sgreen ; 86657429Smarkm 86757429Smarkm /* Read data from the socket. */ 86857429Smarkm len = read(connection_in, buf, sizeof(buf)); 86957429Smarkm if (len == 0) { 870124208Sdes logit("Connection closed by %.200s", get_remote_ipaddr()); 871126274Sdes cleanup_exit(255); 87257429Smarkm } 87357429Smarkm if (len < 0) 87457429Smarkm fatal("Read from socket failed: %.100s", strerror(errno)); 87557429Smarkm /* Append it to the buffer. */ 87657429Smarkm packet_process_incoming(buf, len); 87757429Smarkm } 87857429Smarkm /* NOTREACHED */ 87957429Smarkm} 88057429Smarkm 88192555Sdesint 88292555Sdespacket_read(void) 88392555Sdes{ 88492555Sdes return packet_read_seqnr(NULL); 88592555Sdes} 88692555Sdes 88757429Smarkm/* 88857429Smarkm * Waits until a packet has been received, verifies that its type matches 88957429Smarkm * that given, and gives a fatal error and exits if there is a mismatch. 89057429Smarkm */ 89157429Smarkm 89257429Smarkmvoid 89392555Sdespacket_read_expect(int expected_type) 89457429Smarkm{ 89557429Smarkm int type; 89657429Smarkm 89792555Sdes type = packet_read(); 89857429Smarkm if (type != expected_type) 89957429Smarkm packet_disconnect("Protocol error: expected packet type %d, got %d", 90060573Skris expected_type, type); 90157429Smarkm} 90257429Smarkm 90357429Smarkm/* Checks if a full packet is available in the data received so far via 90457429Smarkm * packet_process_incoming. If so, reads the packet; otherwise returns 90557429Smarkm * SSH_MSG_NONE. This does not wait for data from the connection. 90657429Smarkm * 90757429Smarkm * SSH_MSG_DISCONNECT is handled specially here. Also, 90857429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned 90957429Smarkm * to higher levels. 91057429Smarkm */ 91157429Smarkm 91292555Sdesstatic int 91392555Sdespacket_read_poll1(void) 91457429Smarkm{ 91576259Sgreen u_int len, padded_len; 91692555Sdes u_char *cp, type; 91776259Sgreen u_int checksum, stored_checksum; 91857429Smarkm 91957429Smarkm /* Check if input size is less than minimum packet size. */ 92057429Smarkm if (buffer_len(&input) < 4 + 8) 92157429Smarkm return SSH_MSG_NONE; 92257429Smarkm /* Get length of incoming packet. */ 92392555Sdes cp = buffer_ptr(&input); 92492555Sdes len = GET_32BIT(cp); 92557429Smarkm if (len < 1 + 2 + 2 || len > 256 * 1024) 926113908Sdes packet_disconnect("Bad packet length %u.", len); 92757429Smarkm padded_len = (len + 8) & ~7; 92857429Smarkm 92957429Smarkm /* Check if the packet has been entirely received. */ 93057429Smarkm if (buffer_len(&input) < 4 + padded_len) 93157429Smarkm return SSH_MSG_NONE; 93257429Smarkm 93357429Smarkm /* The entire packet is in buffer. */ 93457429Smarkm 93557429Smarkm /* Consume packet length. */ 93657429Smarkm buffer_consume(&input, 4); 93757429Smarkm 93892555Sdes /* 93992555Sdes * Cryptographic attack detector for ssh 94092555Sdes * (C)1998 CORE-SDI, Buenos Aires Argentina 94192555Sdes * Ariel Futoransky(futo@core-sdi.com) 94292555Sdes */ 94392555Sdes if (!receive_context.plaintext && 94492555Sdes detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED) 94592555Sdes packet_disconnect("crc32 compensation attack: network attack detected"); 94692555Sdes 94792555Sdes /* Decrypt data to incoming_packet. */ 94857429Smarkm buffer_clear(&incoming_packet); 94992555Sdes cp = buffer_append_space(&incoming_packet, padded_len); 95092555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); 95192555Sdes 95257429Smarkm buffer_consume(&input, padded_len); 95357429Smarkm 95457429Smarkm#ifdef PACKET_DEBUG 95557429Smarkm fprintf(stderr, "read_poll plain: "); 95657429Smarkm buffer_dump(&incoming_packet); 95757429Smarkm#endif 95857429Smarkm 95957429Smarkm /* Compute packet checksum. */ 96092555Sdes checksum = ssh_crc32(buffer_ptr(&incoming_packet), 96160573Skris buffer_len(&incoming_packet) - 4); 96257429Smarkm 96357429Smarkm /* Skip padding. */ 96457429Smarkm buffer_consume(&incoming_packet, 8 - len % 8); 96557429Smarkm 96657429Smarkm /* Test check bytes. */ 96757429Smarkm if (len != buffer_len(&incoming_packet)) 96892555Sdes packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 96960573Skris len, buffer_len(&incoming_packet)); 97057429Smarkm 97192555Sdes cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; 97292555Sdes stored_checksum = GET_32BIT(cp); 97357429Smarkm if (checksum != stored_checksum) 97457429Smarkm packet_disconnect("Corrupted check bytes on input."); 97557429Smarkm buffer_consume_end(&incoming_packet, 4); 97657429Smarkm 97757429Smarkm if (packet_compression) { 97857429Smarkm buffer_clear(&compression_buffer); 97957429Smarkm buffer_uncompress(&incoming_packet, &compression_buffer); 98057429Smarkm buffer_clear(&incoming_packet); 98157429Smarkm buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 98260573Skris buffer_len(&compression_buffer)); 98357429Smarkm } 98492555Sdes type = buffer_get_char(&incoming_packet); 98592555Sdes return type; 98660573Skris} 98757429Smarkm 98892555Sdesstatic int 98992555Sdespacket_read_poll2(u_int32_t *seqnr_p) 99060573Skris{ 99176259Sgreen static u_int packet_length = 0; 99276259Sgreen u_int padlen, need; 99392555Sdes u_char *macbuf, *cp, type; 99460573Skris int maclen, block_size; 99560573Skris Enc *enc = NULL; 99660573Skris Mac *mac = NULL; 99760573Skris Comp *comp = NULL; 99857429Smarkm 99976259Sgreen if (newkeys[MODE_IN] != NULL) { 100076259Sgreen enc = &newkeys[MODE_IN]->enc; 100176259Sgreen mac = &newkeys[MODE_IN]->mac; 100276259Sgreen comp = &newkeys[MODE_IN]->comp; 100357429Smarkm } 100460573Skris maclen = mac && mac->enabled ? mac->mac_len : 0; 100592555Sdes block_size = enc ? enc->block_size : 8; 100660573Skris 100760573Skris if (packet_length == 0) { 100860573Skris /* 100960573Skris * check if input size is less than the cipher block size, 101060573Skris * decrypt first block and extract length of incoming packet 101160573Skris */ 101260573Skris if (buffer_len(&input) < block_size) 101360573Skris return SSH_MSG_NONE; 101460573Skris buffer_clear(&incoming_packet); 101592555Sdes cp = buffer_append_space(&incoming_packet, block_size); 101692555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), 101760573Skris block_size); 101892555Sdes cp = buffer_ptr(&incoming_packet); 101992555Sdes packet_length = GET_32BIT(cp); 102060573Skris if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 1021124208Sdes#ifdef PACKET_DEBUG 102260573Skris buffer_dump(&incoming_packet); 1023124208Sdes#endif 1024113908Sdes packet_disconnect("Bad packet length %u.", packet_length); 102560573Skris } 1026113908Sdes DBG(debug("input: packet len %u", packet_length+4)); 102760573Skris buffer_consume(&input, block_size); 102860573Skris } 102960573Skris /* we have a partial packet of block_size bytes */ 103060573Skris need = 4 + packet_length - block_size; 103160573Skris DBG(debug("partial packet %d, need %d, maclen %d", block_size, 103260573Skris need, maclen)); 103360573Skris if (need % block_size != 0) 103460573Skris fatal("padding error: need %d block %d mod %d", 103560573Skris need, block_size, need % block_size); 103660573Skris /* 103760573Skris * check if the entire packet has been received and 103860573Skris * decrypt into incoming_packet 103960573Skris */ 104060573Skris if (buffer_len(&input) < need + maclen) 104160573Skris return SSH_MSG_NONE; 104260573Skris#ifdef PACKET_DEBUG 104360573Skris fprintf(stderr, "read_poll enc/full: "); 104460573Skris buffer_dump(&input); 104560573Skris#endif 104692555Sdes cp = buffer_append_space(&incoming_packet, need); 104792555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); 104860573Skris buffer_consume(&input, need); 104960573Skris /* 105060573Skris * compute MAC over seqnr and packet, 105160573Skris * increment sequence number for incoming packet 105260573Skris */ 105360573Skris if (mac && mac->enabled) { 1054124208Sdes macbuf = mac_compute(mac, p_read.seqnr, 105592555Sdes buffer_ptr(&incoming_packet), 105676259Sgreen buffer_len(&incoming_packet)); 105760573Skris if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 105869587Sgreen packet_disconnect("Corrupted MAC on input."); 1059124208Sdes DBG(debug("MAC #%d ok", p_read.seqnr)); 106060573Skris buffer_consume(&input, mac->mac_len); 106160573Skris } 106292555Sdes if (seqnr_p != NULL) 1063124208Sdes *seqnr_p = p_read.seqnr; 1064124208Sdes if (++p_read.seqnr == 0) 1065124208Sdes logit("incoming seqnr wraps around"); 1066124208Sdes if (++p_read.packets == 0) 1067124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 1068124208Sdes fatal("XXX too many packets with same key"); 1069124208Sdes p_read.blocks += (packet_length + 4) / block_size; 107060573Skris 107160573Skris /* get padlen */ 107292555Sdes cp = buffer_ptr(&incoming_packet); 107392555Sdes padlen = cp[4]; 107460573Skris DBG(debug("input: padlen %d", padlen)); 107560573Skris if (padlen < 4) 107660573Skris packet_disconnect("Corrupted padlen %d on input.", padlen); 107760573Skris 107860573Skris /* skip packet size + padlen, discard padding */ 107960573Skris buffer_consume(&incoming_packet, 4 + 1); 108060573Skris buffer_consume_end(&incoming_packet, padlen); 108160573Skris 108260573Skris DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); 108360573Skris if (comp && comp->enabled) { 108460573Skris buffer_clear(&compression_buffer); 108560573Skris buffer_uncompress(&incoming_packet, &compression_buffer); 108660573Skris buffer_clear(&incoming_packet); 108760573Skris buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 108860573Skris buffer_len(&compression_buffer)); 1089106121Sdes DBG(debug("input: len after de-compress %d", 1090106121Sdes buffer_len(&incoming_packet))); 109160573Skris } 109260573Skris /* 109360573Skris * get packet type, implies consume. 109460573Skris * return length of payload (without type field) 109560573Skris */ 109692555Sdes type = buffer_get_char(&incoming_packet); 109776259Sgreen if (type == SSH2_MSG_NEWKEYS) 109876259Sgreen set_newkeys(MODE_IN); 109960573Skris#ifdef PACKET_DEBUG 110076259Sgreen fprintf(stderr, "read/plain[%d]:\r\n", type); 110160573Skris buffer_dump(&incoming_packet); 110260573Skris#endif 110392555Sdes /* reset for next packet */ 110492555Sdes packet_length = 0; 110592555Sdes return type; 110657429Smarkm} 110757429Smarkm 110860573Skrisint 110992555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p) 111060573Skris{ 111199060Sdes u_int reason, seqnr; 111292555Sdes u_char type; 111360573Skris char *msg; 111492555Sdes 111560573Skris for (;;) { 111692555Sdes if (compat20) { 111792555Sdes type = packet_read_poll2(seqnr_p); 111892555Sdes if (type) 111960573Skris DBG(debug("received packet type %d", type)); 112092555Sdes switch (type) { 112160573Skris case SSH2_MSG_IGNORE: 112260573Skris break; 112360573Skris case SSH2_MSG_DEBUG: 112460573Skris packet_get_char(); 112560573Skris msg = packet_get_string(NULL); 112660573Skris debug("Remote: %.900s", msg); 112760573Skris xfree(msg); 112860573Skris msg = packet_get_string(NULL); 112960573Skris xfree(msg); 113060573Skris break; 113160573Skris case SSH2_MSG_DISCONNECT: 113260573Skris reason = packet_get_int(); 113360573Skris msg = packet_get_string(NULL); 1134124208Sdes logit("Received disconnect from %s: %u: %.400s", 113599060Sdes get_remote_ipaddr(), reason, msg); 113660573Skris xfree(msg); 1137126274Sdes cleanup_exit(255); 113860573Skris break; 113992555Sdes case SSH2_MSG_UNIMPLEMENTED: 114092555Sdes seqnr = packet_get_int(); 114199060Sdes debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 114299060Sdes seqnr); 114392555Sdes break; 114460573Skris default: 114560573Skris return type; 114660573Skris break; 114776259Sgreen } 114860573Skris } else { 114992555Sdes type = packet_read_poll1(); 115092555Sdes switch (type) { 115160573Skris case SSH_MSG_IGNORE: 115260573Skris break; 115360573Skris case SSH_MSG_DEBUG: 115460573Skris msg = packet_get_string(NULL); 115560573Skris debug("Remote: %.900s", msg); 115660573Skris xfree(msg); 115760573Skris break; 115860573Skris case SSH_MSG_DISCONNECT: 115960573Skris msg = packet_get_string(NULL); 1160124208Sdes logit("Received disconnect from %s: %.400s", 116199060Sdes get_remote_ipaddr(), msg); 1162126274Sdes cleanup_exit(255); 116360573Skris xfree(msg); 116460573Skris break; 116560573Skris default: 116692555Sdes if (type) 116760573Skris DBG(debug("received packet type %d", type)); 116860573Skris return type; 116960573Skris break; 117076259Sgreen } 117160573Skris } 117260573Skris } 117360573Skris} 117460573Skris 117592555Sdesint 117692555Sdespacket_read_poll(void) 117792555Sdes{ 117892555Sdes return packet_read_poll_seqnr(NULL); 117992555Sdes} 118092555Sdes 118157429Smarkm/* 118257429Smarkm * Buffers the given amount of input characters. This is intended to be used 118357429Smarkm * together with packet_read_poll. 118457429Smarkm */ 118557429Smarkm 118657429Smarkmvoid 118776259Sgreenpacket_process_incoming(const char *buf, u_int len) 118857429Smarkm{ 118957429Smarkm buffer_append(&input, buf, len); 119057429Smarkm} 119157429Smarkm 119257429Smarkm/* Returns a character from the packet. */ 119357429Smarkm 119476259Sgreenu_int 119592555Sdespacket_get_char(void) 119657429Smarkm{ 119757429Smarkm char ch; 1198106121Sdes 119957429Smarkm buffer_get(&incoming_packet, &ch, 1); 120076259Sgreen return (u_char) ch; 120157429Smarkm} 120257429Smarkm 120357429Smarkm/* Returns an integer from the packet data. */ 120457429Smarkm 120576259Sgreenu_int 120692555Sdespacket_get_int(void) 120757429Smarkm{ 120857429Smarkm return buffer_get_int(&incoming_packet); 120957429Smarkm} 121057429Smarkm 121157429Smarkm/* 121257429Smarkm * Returns an arbitrary precision integer from the packet data. The integer 121357429Smarkm * must have been initialized before this call. 121457429Smarkm */ 121557429Smarkm 121657429Smarkmvoid 121792555Sdespacket_get_bignum(BIGNUM * value) 121857429Smarkm{ 121992555Sdes buffer_get_bignum(&incoming_packet, value); 122057429Smarkm} 122157429Smarkm 122260573Skrisvoid 122392555Sdespacket_get_bignum2(BIGNUM * value) 122460573Skris{ 122592555Sdes buffer_get_bignum2(&incoming_packet, value); 122660573Skris} 122760573Skris 122892555Sdesvoid * 122960573Skrispacket_get_raw(int *length_ptr) 123060573Skris{ 123160573Skris int bytes = buffer_len(&incoming_packet); 1232106121Sdes 123360573Skris if (length_ptr != NULL) 123460573Skris *length_ptr = bytes; 123560573Skris return buffer_ptr(&incoming_packet); 123660573Skris} 123760573Skris 123860573Skrisint 123960573Skrispacket_remaining(void) 124060573Skris{ 124160573Skris return buffer_len(&incoming_packet); 124260573Skris} 124360573Skris 124457429Smarkm/* 124557429Smarkm * Returns a string from the packet data. The string is allocated using 124657429Smarkm * xmalloc; it is the responsibility of the calling program to free it when 124757429Smarkm * no longer needed. The length_ptr argument may be NULL, or point to an 124857429Smarkm * integer into which the length of the string is stored. 124957429Smarkm */ 125057429Smarkm 125192555Sdesvoid * 125276259Sgreenpacket_get_string(u_int *length_ptr) 125357429Smarkm{ 125457429Smarkm return buffer_get_string(&incoming_packet, length_ptr); 125557429Smarkm} 125657429Smarkm 125757429Smarkm/* 125857429Smarkm * Sends a diagnostic message from the server to the client. This message 125957429Smarkm * can be sent at any time (but not while constructing another message). The 126057429Smarkm * message is printed immediately, but only if the client is being executed 126157429Smarkm * in verbose mode. These messages are primarily intended to ease debugging 126257429Smarkm * authentication problems. The length of the formatted message must not 126357429Smarkm * exceed 1024 bytes. This will automatically call packet_write_wait. 126457429Smarkm */ 126557429Smarkm 126657429Smarkmvoid 126757429Smarkmpacket_send_debug(const char *fmt,...) 126857429Smarkm{ 126957429Smarkm char buf[1024]; 127057429Smarkm va_list args; 127157429Smarkm 127276259Sgreen if (compat20 && (datafellows & SSH_BUG_DEBUG)) 127376259Sgreen return; 127476259Sgreen 127557429Smarkm va_start(args, fmt); 127657429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 127757429Smarkm va_end(args); 127857429Smarkm 127960573Skris if (compat20) { 128060573Skris packet_start(SSH2_MSG_DEBUG); 128160573Skris packet_put_char(0); /* bool: always display */ 128260573Skris packet_put_cstring(buf); 128360573Skris packet_put_cstring(""); 128460573Skris } else { 128560573Skris packet_start(SSH_MSG_DEBUG); 128660573Skris packet_put_cstring(buf); 128760573Skris } 128857429Smarkm packet_send(); 128957429Smarkm packet_write_wait(); 129057429Smarkm} 129157429Smarkm 129257429Smarkm/* 129357429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the 129457429Smarkm * connection, and exits. This function never returns. The error message 129557429Smarkm * should not contain a newline. The length of the formatted message must 129657429Smarkm * not exceed 1024 bytes. 129757429Smarkm */ 129857429Smarkm 129957429Smarkmvoid 130057429Smarkmpacket_disconnect(const char *fmt,...) 130157429Smarkm{ 130257429Smarkm char buf[1024]; 130357429Smarkm va_list args; 130457429Smarkm static int disconnecting = 0; 1305106121Sdes 130657429Smarkm if (disconnecting) /* Guard against recursive invocations. */ 130757429Smarkm fatal("packet_disconnect called recursively."); 130857429Smarkm disconnecting = 1; 130957429Smarkm 131057429Smarkm /* 131157429Smarkm * Format the message. Note that the caller must make sure the 131257429Smarkm * message is of limited size. 131357429Smarkm */ 131457429Smarkm va_start(args, fmt); 131557429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 131657429Smarkm va_end(args); 131757429Smarkm 1318113908Sdes /* Display the error locally */ 1319124208Sdes logit("Disconnecting: %.100s", buf); 1320113908Sdes 132157429Smarkm /* Send the disconnect message to the other side, and wait for it to get sent. */ 132260573Skris if (compat20) { 132360573Skris packet_start(SSH2_MSG_DISCONNECT); 132460573Skris packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 132560573Skris packet_put_cstring(buf); 132660573Skris packet_put_cstring(""); 132760573Skris } else { 132860573Skris packet_start(SSH_MSG_DISCONNECT); 132992555Sdes packet_put_cstring(buf); 133060573Skris } 133157429Smarkm packet_send(); 133257429Smarkm packet_write_wait(); 133357429Smarkm 133457429Smarkm /* Stop listening for connections. */ 133592555Sdes channel_close_all(); 133657429Smarkm 133757429Smarkm /* Close the connection. */ 133857429Smarkm packet_close(); 1339126274Sdes cleanup_exit(255); 134057429Smarkm} 134157429Smarkm 134257429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */ 134357429Smarkm 134457429Smarkmvoid 134592555Sdespacket_write_poll(void) 134657429Smarkm{ 134757429Smarkm int len = buffer_len(&output); 1348106121Sdes 134957429Smarkm if (len > 0) { 135057429Smarkm len = write(connection_out, buffer_ptr(&output), len); 135157429Smarkm if (len <= 0) { 135257429Smarkm if (errno == EAGAIN) 135357429Smarkm return; 135457429Smarkm else 135557429Smarkm fatal("Write failed: %.100s", strerror(errno)); 135657429Smarkm } 135757429Smarkm buffer_consume(&output, len); 135857429Smarkm } 135957429Smarkm} 136057429Smarkm 136157429Smarkm/* 136257429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been 136357429Smarkm * written. 136457429Smarkm */ 136557429Smarkm 136657429Smarkmvoid 136792555Sdespacket_write_wait(void) 136857429Smarkm{ 136976259Sgreen fd_set *setp; 137076259Sgreen 137176259Sgreen setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) * 137276259Sgreen sizeof(fd_mask)); 137357429Smarkm packet_write_poll(); 137457429Smarkm while (packet_have_data_to_write()) { 137576259Sgreen memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 137676259Sgreen sizeof(fd_mask)); 137776259Sgreen FD_SET(connection_out, setp); 137876259Sgreen while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && 137976259Sgreen (errno == EAGAIN || errno == EINTR)) 138076259Sgreen ; 138157429Smarkm packet_write_poll(); 138257429Smarkm } 138376259Sgreen xfree(setp); 138457429Smarkm} 138557429Smarkm 138657429Smarkm/* Returns true if there is buffered data to write to the connection. */ 138757429Smarkm 138857429Smarkmint 138992555Sdespacket_have_data_to_write(void) 139057429Smarkm{ 139157429Smarkm return buffer_len(&output) != 0; 139257429Smarkm} 139357429Smarkm 139457429Smarkm/* Returns true if there is not too much data to write to the connection. */ 139557429Smarkm 139657429Smarkmint 139792555Sdespacket_not_very_much_data_to_write(void) 139857429Smarkm{ 139957429Smarkm if (interactive_mode) 140057429Smarkm return buffer_len(&output) < 16384; 140157429Smarkm else 140257429Smarkm return buffer_len(&output) < 128 * 1024; 140357429Smarkm} 140457429Smarkm 1405124208Sdes 1406113908Sdesstatic void 1407113908Sdespacket_set_tos(int interactive) 1408113908Sdes{ 1409126274Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 1410113908Sdes int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT; 1411113908Sdes 1412113908Sdes if (!packet_connection_is_on_socket() || 1413113908Sdes !packet_connection_is_ipv4()) 1414113908Sdes return; 1415113908Sdes if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos, 1416113908Sdes sizeof(tos)) < 0) 1417113908Sdes error("setsockopt IP_TOS %d: %.100s:", 1418113908Sdes tos, strerror(errno)); 1419126274Sdes#endif 1420113908Sdes} 1421113908Sdes 142257429Smarkm/* Informs that the current session is interactive. Sets IP flags for that. */ 142357429Smarkm 142457429Smarkmvoid 142576259Sgreenpacket_set_interactive(int interactive) 142657429Smarkm{ 142776259Sgreen static int called = 0; 142857429Smarkm 142976259Sgreen if (called) 143076259Sgreen return; 143176259Sgreen called = 1; 143276259Sgreen 143357429Smarkm /* Record that we are in interactive mode. */ 143457429Smarkm interactive_mode = interactive; 143557429Smarkm 143657429Smarkm /* Only set socket options if using a socket. */ 143757429Smarkm if (!packet_connection_is_on_socket()) 1438116791Sdes return; 1439113908Sdes if (interactive) 144092555Sdes set_nodelay(connection_in); 1441113908Sdes packet_set_tos(interactive); 144257429Smarkm} 144357429Smarkm 144457429Smarkm/* Returns true if the current connection is interactive. */ 144557429Smarkm 144657429Smarkmint 144792555Sdespacket_is_interactive(void) 144857429Smarkm{ 144957429Smarkm return interactive_mode; 145057429Smarkm} 145157429Smarkm 1452124208Sdesu_int 1453124208Sdespacket_set_maxsize(u_int s) 145457429Smarkm{ 145557429Smarkm static int called = 0; 1456106121Sdes 145757429Smarkm if (called) { 1458124208Sdes logit("packet_set_maxsize: called twice: old %d new %d", 145960573Skris max_packet_size, s); 146057429Smarkm return -1; 146157429Smarkm } 146257429Smarkm if (s < 4 * 1024 || s > 1024 * 1024) { 1463124208Sdes logit("packet_set_maxsize: bad size %d", s); 146457429Smarkm return -1; 146557429Smarkm } 146692555Sdes called = 1; 146792555Sdes debug("packet_set_maxsize: setting to %d", s); 146857429Smarkm max_packet_size = s; 146957429Smarkm return s; 147057429Smarkm} 147176259Sgreen 147292555Sdes/* roundup current message to pad bytes */ 147392555Sdesvoid 147492555Sdespacket_add_padding(u_char pad) 147592555Sdes{ 147692555Sdes extra_pad = pad; 147792555Sdes} 147892555Sdes 147976259Sgreen/* 148076259Sgreen * 9.2. Ignored Data Message 148176259Sgreen * 148276259Sgreen * byte SSH_MSG_IGNORE 148376259Sgreen * string data 148476259Sgreen * 148576259Sgreen * All implementations MUST understand (and ignore) this message at any 148676259Sgreen * time (after receiving the protocol version). No implementation is 148776259Sgreen * required to send them. This message can be used as an additional 148876259Sgreen * protection measure against advanced traffic analysis techniques. 148976259Sgreen */ 149076259Sgreenvoid 149176259Sgreenpacket_send_ignore(int nbytes) 149276259Sgreen{ 149376259Sgreen u_int32_t rand = 0; 149476259Sgreen int i; 149576259Sgreen 149676259Sgreen packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 149776259Sgreen packet_put_int(nbytes); 149892555Sdes for (i = 0; i < nbytes; i++) { 149976259Sgreen if (i % 4 == 0) 150076259Sgreen rand = arc4random(); 150176259Sgreen packet_put_char(rand & 0xff); 150276259Sgreen rand >>= 8; 150376259Sgreen } 150476259Sgreen} 1505124208Sdes 1506124208Sdes#define MAX_PACKETS (1<<31) 1507124208Sdesint 1508124208Sdespacket_need_rekeying(void) 1509124208Sdes{ 1510124208Sdes if (datafellows & SSH_BUG_NOREKEY) 1511124208Sdes return 0; 1512124208Sdes return 1513124208Sdes (p_send.packets > MAX_PACKETS) || 1514124208Sdes (p_read.packets > MAX_PACKETS) || 1515124208Sdes (max_blocks_out && (p_send.blocks > max_blocks_out)) || 1516124208Sdes (max_blocks_in && (p_read.blocks > max_blocks_in)); 1517124208Sdes} 1518124208Sdes 1519124208Sdesvoid 1520124208Sdespacket_set_rekey_limit(u_int32_t bytes) 1521124208Sdes{ 1522124208Sdes rekey_limit = bytes; 1523124208Sdes} 1524