packet.c revision 113908
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" 40113908SdesRCSID("$OpenBSD: packet.c,v 1.104 2003/04/01 10:22:21 markus Exp $"); 4157429Smarkm 4257429Smarkm#include "xmalloc.h" 4357429Smarkm#include "buffer.h" 4457429Smarkm#include "packet.h" 4557429Smarkm#include "bufaux.h" 4657429Smarkm#include "crc32.h" 4757429Smarkm#include "getput.h" 4857429Smarkm 4957429Smarkm#include "compress.h" 5057429Smarkm#include "deattack.h" 5160573Skris#include "channels.h" 5257429Smarkm 5360573Skris#include "compat.h" 5476259Sgreen#include "ssh1.h" 5560573Skris#include "ssh2.h" 5660573Skris 5769587Sgreen#include "cipher.h" 5860573Skris#include "kex.h" 5976259Sgreen#include "mac.h" 6076259Sgreen#include "log.h" 6176259Sgreen#include "canohost.h" 6292555Sdes#include "misc.h" 6398675Sdes#include "ssh.h" 6460573Skris 6560573Skris#ifdef PACKET_DEBUG 6660573Skris#define DBG(x) x 6760573Skris#else 6860573Skris#define DBG(x) 6960573Skris#endif 7060573Skris 7157429Smarkm/* 7257429Smarkm * This variable contains the file descriptors used for communicating with 7357429Smarkm * the other side. connection_in is used for reading; connection_out for 7457429Smarkm * writing. These can be the same descriptor, in which case it is assumed to 7557429Smarkm * be a socket. 7657429Smarkm */ 7757429Smarkmstatic int connection_in = -1; 7857429Smarkmstatic int connection_out = -1; 7957429Smarkm 8057429Smarkm/* Protocol flags for the remote side. */ 8176259Sgreenstatic u_int remote_protocol_flags = 0; 8257429Smarkm 8357429Smarkm/* Encryption context for receiving data. This is only used for decryption. */ 8457429Smarkmstatic CipherContext receive_context; 8557429Smarkm 8657429Smarkm/* Encryption context for sending data. This is only used for encryption. */ 8757429Smarkmstatic CipherContext send_context; 8857429Smarkm 8957429Smarkm/* Buffer for raw input data from the socket. */ 9098675SdesBuffer input; 9157429Smarkm 9257429Smarkm/* Buffer for raw output data going to the socket. */ 9398675SdesBuffer output; 9457429Smarkm 9557429Smarkm/* Buffer for the partial outgoing packet being constructed. */ 9657429Smarkmstatic Buffer outgoing_packet; 9757429Smarkm 9857429Smarkm/* Buffer for the incoming packet currently being processed. */ 9957429Smarkmstatic Buffer incoming_packet; 10057429Smarkm 10157429Smarkm/* Scratch buffer for packet compression/decompression. */ 10257429Smarkmstatic Buffer compression_buffer; 10376259Sgreenstatic int compression_buffer_ready = 0; 10457429Smarkm 10557429Smarkm/* Flag indicating whether packet compression/decompression is enabled. */ 10657429Smarkmstatic int packet_compression = 0; 10757429Smarkm 10857429Smarkm/* default maximum packet size */ 10957429Smarkmint max_packet_size = 32768; 11057429Smarkm 11157429Smarkm/* Flag indicating whether this module has been initialized. */ 11257429Smarkmstatic int initialized = 0; 11357429Smarkm 11457429Smarkm/* Set to true if the connection is interactive. */ 11557429Smarkmstatic int interactive_mode = 0; 11657429Smarkm 11760573Skris/* Session key information for Encryption and MAC */ 11876259SgreenNewkeys *newkeys[MODE_MAX]; 11998675Sdesstatic u_int32_t read_seqnr = 0; 12098675Sdesstatic u_int32_t send_seqnr = 0; 12160573Skris 12298675Sdes/* Session key for protocol v1 */ 12398675Sdesstatic u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 12498675Sdesstatic u_int ssh1_keylen; 12598675Sdes 12692555Sdes/* roundup current message to extra_pad bytes */ 12792555Sdesstatic u_char extra_pad = 0; 12860573Skris 12957429Smarkm/* 13057429Smarkm * Sets the descriptors used for communication. Disables encryption until 13157429Smarkm * packet_set_encryption_key is called. 13257429Smarkm */ 13357429Smarkmvoid 13457429Smarkmpacket_set_connection(int fd_in, int fd_out) 13557429Smarkm{ 13669587Sgreen Cipher *none = cipher_by_name("none"); 137106121Sdes 13869587Sgreen if (none == NULL) 13969587Sgreen fatal("packet_set_connection: cannot load cipher 'none'"); 14057429Smarkm connection_in = fd_in; 14157429Smarkm connection_out = fd_out; 14292555Sdes cipher_init(&send_context, none, "", 0, NULL, 0, CIPHER_ENCRYPT); 14392555Sdes cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT); 14492555Sdes newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL; 14557429Smarkm if (!initialized) { 14657429Smarkm initialized = 1; 14757429Smarkm buffer_init(&input); 14857429Smarkm buffer_init(&output); 14957429Smarkm buffer_init(&outgoing_packet); 15057429Smarkm buffer_init(&incoming_packet); 15157429Smarkm } 15257429Smarkm /* Kludge: arrange the close function to be called from fatal(). */ 15357429Smarkm fatal_add_cleanup((void (*) (void *)) packet_close, NULL); 15457429Smarkm} 15557429Smarkm 15657429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */ 15757429Smarkm 15857429Smarkmint 15992555Sdespacket_connection_is_on_socket(void) 16057429Smarkm{ 16157429Smarkm struct sockaddr_storage from, to; 16257429Smarkm socklen_t fromlen, tolen; 16357429Smarkm 16457429Smarkm /* filedescriptors in and out are the same, so it's a socket */ 16557429Smarkm if (connection_in == connection_out) 16657429Smarkm return 1; 16757429Smarkm fromlen = sizeof(from); 16857429Smarkm memset(&from, 0, sizeof(from)); 16957429Smarkm if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0) 17057429Smarkm return 0; 17157429Smarkm tolen = sizeof(to); 17257429Smarkm memset(&to, 0, sizeof(to)); 17357429Smarkm if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0) 17457429Smarkm return 0; 17557429Smarkm if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) 17657429Smarkm return 0; 17757429Smarkm if (from.ss_family != AF_INET && from.ss_family != AF_INET6) 17857429Smarkm return 0; 17957429Smarkm return 1; 18057429Smarkm} 18157429Smarkm 18298675Sdes/* 18398675Sdes * Exports an IV from the CipherContext required to export the key 18498675Sdes * state back from the unprivileged child to the privileged parent 18598675Sdes * process. 18698675Sdes */ 18798675Sdes 18898675Sdesvoid 18998675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len) 19098675Sdes{ 19198675Sdes CipherContext *cc; 19298675Sdes 19398675Sdes if (mode == MODE_OUT) 19498675Sdes cc = &send_context; 19598675Sdes else 19698675Sdes cc = &receive_context; 19798675Sdes 19898675Sdes cipher_get_keyiv(cc, iv, len); 19998675Sdes} 20098675Sdes 20198675Sdesint 20298675Sdespacket_get_keycontext(int mode, u_char *dat) 20398675Sdes{ 20498675Sdes CipherContext *cc; 20598675Sdes 20698675Sdes if (mode == MODE_OUT) 20798675Sdes cc = &send_context; 20898675Sdes else 20998675Sdes cc = &receive_context; 21098675Sdes 21198675Sdes return (cipher_get_keycontext(cc, dat)); 21298675Sdes} 21398675Sdes 21498675Sdesvoid 21598675Sdespacket_set_keycontext(int mode, u_char *dat) 21698675Sdes{ 21798675Sdes CipherContext *cc; 21898675Sdes 21998675Sdes if (mode == MODE_OUT) 22098675Sdes cc = &send_context; 22198675Sdes else 22298675Sdes cc = &receive_context; 22398675Sdes 22498675Sdes cipher_set_keycontext(cc, dat); 22598675Sdes} 22698675Sdes 22798675Sdesint 22898675Sdespacket_get_keyiv_len(int mode) 22998675Sdes{ 23098675Sdes CipherContext *cc; 23198675Sdes 23298675Sdes if (mode == MODE_OUT) 23398675Sdes cc = &send_context; 23498675Sdes else 23598675Sdes cc = &receive_context; 23698675Sdes 23798675Sdes return (cipher_get_keyiv_len(cc)); 23898675Sdes} 23998675Sdesvoid 24098675Sdespacket_set_iv(int mode, u_char *dat) 24198675Sdes{ 24298675Sdes CipherContext *cc; 24398675Sdes 24498675Sdes if (mode == MODE_OUT) 24598675Sdes cc = &send_context; 24698675Sdes else 24798675Sdes cc = &receive_context; 24898675Sdes 24998675Sdes cipher_set_keyiv(cc, dat); 25098675Sdes} 25198675Sdesint 25298675Sdespacket_get_ssh1_cipher() 25398675Sdes{ 25498675Sdes return (cipher_get_number(receive_context.cipher)); 25598675Sdes} 25698675Sdes 25798675Sdes 25898675Sdesu_int32_t 25998675Sdespacket_get_seqnr(int mode) 26098675Sdes{ 26198675Sdes return (mode == MODE_IN ? read_seqnr : send_seqnr); 26298675Sdes} 26398675Sdes 26498675Sdesvoid 26598675Sdespacket_set_seqnr(int mode, u_int32_t seqnr) 26698675Sdes{ 26798675Sdes if (mode == MODE_IN) 26898675Sdes read_seqnr = seqnr; 26998675Sdes else if (mode == MODE_OUT) 27098675Sdes send_seqnr = seqnr; 27198675Sdes else 27298675Sdes fatal("packet_set_seqnr: bad mode %d", mode); 27398675Sdes} 27498675Sdes 27557429Smarkm/* returns 1 if connection is via ipv4 */ 27657429Smarkm 27757429Smarkmint 27892555Sdespacket_connection_is_ipv4(void) 27957429Smarkm{ 28057429Smarkm struct sockaddr_storage to; 28157429Smarkm socklen_t tolen = sizeof(to); 28257429Smarkm 28357429Smarkm memset(&to, 0, sizeof(to)); 28457429Smarkm if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0) 28557429Smarkm return 0; 28698937Sdes if (to.ss_family == AF_INET) 28798937Sdes return 1; 28898937Sdes#ifdef IPV4_IN_IPV6 28998937Sdes if (to.ss_family == AF_INET6 && 29098937Sdes IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) 29198937Sdes return 1; 29298937Sdes#endif 29398937Sdes return 0; 29457429Smarkm} 29557429Smarkm 29657429Smarkm/* Sets the connection into non-blocking mode. */ 29757429Smarkm 29857429Smarkmvoid 29992555Sdespacket_set_nonblocking(void) 30057429Smarkm{ 30157429Smarkm /* Set the socket into non-blocking mode. */ 30257429Smarkm if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0) 30357429Smarkm error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 30457429Smarkm 30557429Smarkm if (connection_out != connection_in) { 30657429Smarkm if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0) 30757429Smarkm error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 30857429Smarkm } 30957429Smarkm} 31057429Smarkm 31157429Smarkm/* Returns the socket used for reading. */ 31257429Smarkm 31357429Smarkmint 31492555Sdespacket_get_connection_in(void) 31557429Smarkm{ 31657429Smarkm return connection_in; 31757429Smarkm} 31857429Smarkm 31957429Smarkm/* Returns the descriptor used for writing. */ 32057429Smarkm 32157429Smarkmint 32292555Sdespacket_get_connection_out(void) 32357429Smarkm{ 32457429Smarkm return connection_out; 32557429Smarkm} 32657429Smarkm 32757429Smarkm/* Closes the connection and clears and frees internal data structures. */ 32857429Smarkm 32957429Smarkmvoid 33092555Sdespacket_close(void) 33157429Smarkm{ 33257429Smarkm if (!initialized) 33357429Smarkm return; 33457429Smarkm initialized = 0; 33557429Smarkm if (connection_in == connection_out) { 33657429Smarkm shutdown(connection_out, SHUT_RDWR); 33757429Smarkm close(connection_out); 33857429Smarkm } else { 33957429Smarkm close(connection_in); 34057429Smarkm close(connection_out); 34157429Smarkm } 34257429Smarkm buffer_free(&input); 34357429Smarkm buffer_free(&output); 34457429Smarkm buffer_free(&outgoing_packet); 34557429Smarkm buffer_free(&incoming_packet); 34676259Sgreen if (compression_buffer_ready) { 34757429Smarkm buffer_free(&compression_buffer); 34857429Smarkm buffer_compress_uninit(); 34957429Smarkm } 35092555Sdes cipher_cleanup(&send_context); 35192555Sdes cipher_cleanup(&receive_context); 35257429Smarkm} 35357429Smarkm 35457429Smarkm/* Sets remote side protocol flags. */ 35557429Smarkm 35657429Smarkmvoid 35776259Sgreenpacket_set_protocol_flags(u_int protocol_flags) 35857429Smarkm{ 35957429Smarkm remote_protocol_flags = protocol_flags; 36057429Smarkm} 36157429Smarkm 36257429Smarkm/* Returns the remote protocol flags set earlier by the above function. */ 36357429Smarkm 36476259Sgreenu_int 36592555Sdespacket_get_protocol_flags(void) 36657429Smarkm{ 36757429Smarkm return remote_protocol_flags; 36857429Smarkm} 36957429Smarkm 37057429Smarkm/* 37157429Smarkm * Starts packet compression from the next packet on in both directions. 37257429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. 37357429Smarkm */ 37457429Smarkm 37592555Sdesstatic void 37692555Sdespacket_init_compression(void) 37776259Sgreen{ 37876259Sgreen if (compression_buffer_ready == 1) 37976259Sgreen return; 38076259Sgreen compression_buffer_ready = 1; 38176259Sgreen buffer_init(&compression_buffer); 38276259Sgreen} 38376259Sgreen 38476259Sgreenvoid 38557429Smarkmpacket_start_compression(int level) 38657429Smarkm{ 38792555Sdes if (packet_compression && !compat20) 38857429Smarkm fatal("Compression already enabled."); 38957429Smarkm packet_compression = 1; 39076259Sgreen packet_init_compression(); 39176259Sgreen buffer_compress_init_send(level); 39276259Sgreen buffer_compress_init_recv(); 39357429Smarkm} 39457429Smarkm 39557429Smarkm/* 39657429Smarkm * Causes any further packets to be encrypted using the given key. The same 39757429Smarkm * key is used for both sending and reception. However, both directions are 39857429Smarkm * encrypted independently of each other. 39957429Smarkm */ 40098675Sdes 40157429Smarkmvoid 40276259Sgreenpacket_set_encryption_key(const u_char *key, u_int keylen, 40369587Sgreen int number) 40457429Smarkm{ 40569587Sgreen Cipher *cipher = cipher_by_number(number); 406106121Sdes 40769587Sgreen if (cipher == NULL) 40869587Sgreen fatal("packet_set_encryption_key: unknown cipher number %d", number); 40960573Skris if (keylen < 20) 41069587Sgreen fatal("packet_set_encryption_key: keylen too small: %d", keylen); 41198675Sdes if (keylen > SSH_SESSION_KEY_LENGTH) 41298675Sdes fatal("packet_set_encryption_key: keylen too big: %d", keylen); 41398675Sdes memcpy(ssh1_key, key, keylen); 41498675Sdes ssh1_keylen = keylen; 41592555Sdes cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT); 41692555Sdes cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT); 41757429Smarkm} 41857429Smarkm 41998675Sdesu_int 42098675Sdespacket_get_encryption_key(u_char *key) 42198675Sdes{ 42298675Sdes if (key == NULL) 42398675Sdes return (ssh1_keylen); 42498675Sdes memcpy(key, ssh1_key, ssh1_keylen); 42598675Sdes return (ssh1_keylen); 42698675Sdes} 42798675Sdes 42892555Sdes/* Start constructing a packet to send. */ 42957429Smarkmvoid 43092555Sdespacket_start(u_char type) 43157429Smarkm{ 43292555Sdes u_char buf[9]; 43392555Sdes int len; 43457429Smarkm 43592555Sdes DBG(debug("packet_start[%d]", type)); 43692555Sdes len = compat20 ? 6 : 9; 43792555Sdes memset(buf, 0, len - 1); 43892555Sdes buf[len - 1] = type; 43957429Smarkm buffer_clear(&outgoing_packet); 44092555Sdes buffer_append(&outgoing_packet, buf, len); 44157429Smarkm} 44257429Smarkm 44392555Sdes/* Append payload. */ 44460573Skrisvoid 44557429Smarkmpacket_put_char(int value) 44657429Smarkm{ 44757429Smarkm char ch = value; 448106121Sdes 44957429Smarkm buffer_append(&outgoing_packet, &ch, 1); 45057429Smarkm} 45157429Smarkmvoid 45276259Sgreenpacket_put_int(u_int value) 45357429Smarkm{ 45457429Smarkm buffer_put_int(&outgoing_packet, value); 45557429Smarkm} 45657429Smarkmvoid 45792555Sdespacket_put_string(const void *buf, u_int len) 45857429Smarkm{ 45957429Smarkm buffer_put_string(&outgoing_packet, buf, len); 46057429Smarkm} 46160573Skrisvoid 46260573Skrispacket_put_cstring(const char *str) 46360573Skris{ 46492555Sdes buffer_put_cstring(&outgoing_packet, str); 46560573Skris} 46660573Skrisvoid 46792555Sdespacket_put_raw(const void *buf, u_int len) 46860573Skris{ 46960573Skris buffer_append(&outgoing_packet, buf, len); 47060573Skris} 47157429Smarkmvoid 47257429Smarkmpacket_put_bignum(BIGNUM * value) 47357429Smarkm{ 47457429Smarkm buffer_put_bignum(&outgoing_packet, value); 47557429Smarkm} 47660573Skrisvoid 47760573Skrispacket_put_bignum2(BIGNUM * value) 47860573Skris{ 47960573Skris buffer_put_bignum2(&outgoing_packet, value); 48060573Skris} 48157429Smarkm 48257429Smarkm/* 48357429Smarkm * Finalizes and sends the packet. If the encryption key has been set, 48457429Smarkm * encrypts the packet before sending. 48557429Smarkm */ 48657429Smarkm 48792555Sdesstatic void 48876259Sgreenpacket_send1(void) 48957429Smarkm{ 49092555Sdes u_char buf[8], *cp; 49157429Smarkm int i, padding, len; 49276259Sgreen u_int checksum; 49357429Smarkm u_int32_t rand = 0; 49457429Smarkm 49557429Smarkm /* 49657429Smarkm * If using packet compression, compress the payload of the outgoing 49757429Smarkm * packet. 49857429Smarkm */ 49957429Smarkm if (packet_compression) { 50057429Smarkm buffer_clear(&compression_buffer); 50157429Smarkm /* Skip padding. */ 50257429Smarkm buffer_consume(&outgoing_packet, 8); 50357429Smarkm /* padding */ 50457429Smarkm buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8); 50557429Smarkm buffer_compress(&outgoing_packet, &compression_buffer); 50657429Smarkm buffer_clear(&outgoing_packet); 50757429Smarkm buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 50892555Sdes buffer_len(&compression_buffer)); 50957429Smarkm } 51057429Smarkm /* Compute packet length without padding (add checksum, remove padding). */ 51157429Smarkm len = buffer_len(&outgoing_packet) + 4 - 8; 51257429Smarkm 51360573Skris /* Insert padding. Initialized to zero in packet_start1() */ 51457429Smarkm padding = 8 - len % 8; 51592555Sdes if (!send_context.plaintext) { 51657429Smarkm cp = buffer_ptr(&outgoing_packet); 51757429Smarkm for (i = 0; i < padding; i++) { 51857429Smarkm if (i % 4 == 0) 51957429Smarkm rand = arc4random(); 52057429Smarkm cp[7 - i] = rand & 0xff; 52157429Smarkm rand >>= 8; 52257429Smarkm } 52357429Smarkm } 52457429Smarkm buffer_consume(&outgoing_packet, 8 - padding); 52557429Smarkm 52657429Smarkm /* Add check bytes. */ 52792555Sdes checksum = ssh_crc32(buffer_ptr(&outgoing_packet), 52865668Skris buffer_len(&outgoing_packet)); 52957429Smarkm PUT_32BIT(buf, checksum); 53057429Smarkm buffer_append(&outgoing_packet, buf, 4); 53157429Smarkm 53257429Smarkm#ifdef PACKET_DEBUG 53357429Smarkm fprintf(stderr, "packet_send plain: "); 53457429Smarkm buffer_dump(&outgoing_packet); 53557429Smarkm#endif 53657429Smarkm 53757429Smarkm /* Append to output. */ 53857429Smarkm PUT_32BIT(buf, len); 53957429Smarkm buffer_append(&output, buf, 4); 54092555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 54192555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 54292555Sdes buffer_len(&outgoing_packet)); 54357429Smarkm 54457429Smarkm#ifdef PACKET_DEBUG 54557429Smarkm fprintf(stderr, "encrypted: "); 54657429Smarkm buffer_dump(&output); 54757429Smarkm#endif 54857429Smarkm 54957429Smarkm buffer_clear(&outgoing_packet); 55057429Smarkm 55157429Smarkm /* 55257429Smarkm * Note that the packet is now only buffered in output. It won\'t be 55357429Smarkm * actually sent until packet_write_wait or packet_write_poll is 55457429Smarkm * called. 55557429Smarkm */ 55657429Smarkm} 55757429Smarkm 55898675Sdesvoid 55976259Sgreenset_newkeys(int mode) 56076259Sgreen{ 56176259Sgreen Enc *enc; 56276259Sgreen Mac *mac; 56376259Sgreen Comp *comp; 56476259Sgreen CipherContext *cc; 56592555Sdes int encrypt; 56676259Sgreen 567113908Sdes debug2("set_newkeys: mode %d", mode); 56876259Sgreen 56992555Sdes if (mode == MODE_OUT) { 57092555Sdes cc = &send_context; 57192555Sdes encrypt = CIPHER_ENCRYPT; 57292555Sdes } else { 57392555Sdes cc = &receive_context; 57492555Sdes encrypt = CIPHER_DECRYPT; 57592555Sdes } 57676259Sgreen if (newkeys[mode] != NULL) { 577113908Sdes debug("set_newkeys: rekeying"); 57892555Sdes cipher_cleanup(cc); 57976259Sgreen enc = &newkeys[mode]->enc; 58076259Sgreen mac = &newkeys[mode]->mac; 58176259Sgreen comp = &newkeys[mode]->comp; 58276259Sgreen memset(mac->key, 0, mac->key_len); 58376259Sgreen xfree(enc->name); 58476259Sgreen xfree(enc->iv); 58576259Sgreen xfree(enc->key); 58676259Sgreen xfree(mac->name); 58776259Sgreen xfree(mac->key); 58876259Sgreen xfree(comp->name); 58976259Sgreen xfree(newkeys[mode]); 59076259Sgreen } 59176259Sgreen newkeys[mode] = kex_get_newkeys(mode); 59276259Sgreen if (newkeys[mode] == NULL) 59376259Sgreen fatal("newkeys: no keys for mode %d", mode); 59476259Sgreen enc = &newkeys[mode]->enc; 59576259Sgreen mac = &newkeys[mode]->mac; 59676259Sgreen comp = &newkeys[mode]->comp; 59776259Sgreen if (mac->md != NULL) 59876259Sgreen mac->enabled = 1; 59976259Sgreen DBG(debug("cipher_init_context: %d", mode)); 60092555Sdes cipher_init(cc, enc->cipher, enc->key, enc->key_len, 60192555Sdes enc->iv, enc->block_size, encrypt); 60298675Sdes /* Deleting the keys does not gain extra security */ 60398675Sdes /* memset(enc->iv, 0, enc->block_size); 60498675Sdes memset(enc->key, 0, enc->key_len); */ 60576259Sgreen if (comp->type != 0 && comp->enabled == 0) { 60676259Sgreen packet_init_compression(); 60776259Sgreen if (mode == MODE_OUT) 60876259Sgreen buffer_compress_init_send(6); 60976259Sgreen else 61076259Sgreen buffer_compress_init_recv(); 61176259Sgreen comp->enabled = 1; 61276259Sgreen } 61376259Sgreen} 61476259Sgreen 61557429Smarkm/* 61660573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 61760573Skris */ 61892555Sdesstatic void 61976259Sgreenpacket_send2(void) 62060573Skris{ 62192555Sdes u_char type, *cp, *macbuf = NULL; 62292555Sdes u_char padlen, pad; 62376259Sgreen u_int packet_length = 0; 62492555Sdes u_int i, len; 62560573Skris u_int32_t rand = 0; 62660573Skris Enc *enc = NULL; 62760573Skris Mac *mac = NULL; 62860573Skris Comp *comp = NULL; 62960573Skris int block_size; 63060573Skris 63176259Sgreen if (newkeys[MODE_OUT] != NULL) { 63276259Sgreen enc = &newkeys[MODE_OUT]->enc; 63376259Sgreen mac = &newkeys[MODE_OUT]->mac; 63476259Sgreen comp = &newkeys[MODE_OUT]->comp; 63560573Skris } 63692555Sdes block_size = enc ? enc->block_size : 8; 63760573Skris 63860573Skris cp = buffer_ptr(&outgoing_packet); 63992555Sdes type = cp[5]; 64060573Skris 64160573Skris#ifdef PACKET_DEBUG 64260573Skris fprintf(stderr, "plain: "); 64360573Skris buffer_dump(&outgoing_packet); 64460573Skris#endif 64560573Skris 64660573Skris if (comp && comp->enabled) { 64760573Skris len = buffer_len(&outgoing_packet); 64860573Skris /* skip header, compress only payload */ 64960573Skris buffer_consume(&outgoing_packet, 5); 65060573Skris buffer_clear(&compression_buffer); 65160573Skris buffer_compress(&outgoing_packet, &compression_buffer); 65260573Skris buffer_clear(&outgoing_packet); 65360573Skris buffer_append(&outgoing_packet, "\0\0\0\0\0", 5); 65460573Skris buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer), 65560573Skris buffer_len(&compression_buffer)); 65660573Skris DBG(debug("compression: raw %d compressed %d", len, 65760573Skris buffer_len(&outgoing_packet))); 65860573Skris } 65960573Skris 66060573Skris /* sizeof (packet_len + pad_len + payload) */ 66160573Skris len = buffer_len(&outgoing_packet); 66260573Skris 66360573Skris /* 66460573Skris * calc size of padding, alloc space, get random data, 66560573Skris * minimum padding is 4 bytes 66660573Skris */ 66760573Skris padlen = block_size - (len % block_size); 66860573Skris if (padlen < 4) 66960573Skris padlen += block_size; 67092555Sdes if (extra_pad) { 67192555Sdes /* will wrap if extra_pad+padlen > 255 */ 67292555Sdes extra_pad = roundup(extra_pad, block_size); 67392555Sdes pad = extra_pad - ((len + padlen) % extra_pad); 67498675Sdes debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 67592555Sdes pad, len, padlen, extra_pad); 67692555Sdes padlen += pad; 67792555Sdes extra_pad = 0; 67892555Sdes } 67992555Sdes cp = buffer_append_space(&outgoing_packet, padlen); 68092555Sdes if (enc && !send_context.plaintext) { 68160573Skris /* random padding */ 68260573Skris for (i = 0; i < padlen; i++) { 68360573Skris if (i % 4 == 0) 68460573Skris rand = arc4random(); 68560573Skris cp[i] = rand & 0xff; 68676259Sgreen rand >>= 8; 68760573Skris } 68860573Skris } else { 68960573Skris /* clear padding */ 69060573Skris memset(cp, 0, padlen); 69160573Skris } 69260573Skris /* packet_length includes payload, padding and padding length field */ 69360573Skris packet_length = buffer_len(&outgoing_packet) - 4; 69460573Skris cp = buffer_ptr(&outgoing_packet); 69560573Skris PUT_32BIT(cp, packet_length); 69692555Sdes cp[4] = padlen; 69760573Skris DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen)); 69860573Skris 69960573Skris /* compute MAC over seqnr and packet(length fields, payload, padding) */ 70060573Skris if (mac && mac->enabled) { 70198675Sdes macbuf = mac_compute(mac, send_seqnr, 70292555Sdes buffer_ptr(&outgoing_packet), 70376259Sgreen buffer_len(&outgoing_packet)); 70498675Sdes DBG(debug("done calc MAC out #%d", send_seqnr)); 70560573Skris } 70660573Skris /* encrypt packet and append to output buffer. */ 70792555Sdes cp = buffer_append_space(&output, buffer_len(&outgoing_packet)); 70892555Sdes cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet), 70960573Skris buffer_len(&outgoing_packet)); 71060573Skris /* append unencrypted MAC */ 71160573Skris if (mac && mac->enabled) 71260573Skris buffer_append(&output, (char *)macbuf, mac->mac_len); 71360573Skris#ifdef PACKET_DEBUG 71460573Skris fprintf(stderr, "encrypted: "); 71560573Skris buffer_dump(&output); 71660573Skris#endif 71760573Skris /* increment sequence number for outgoing packets */ 71898675Sdes if (++send_seqnr == 0) 71960573Skris log("outgoing seqnr wraps around"); 72060573Skris buffer_clear(&outgoing_packet); 72160573Skris 72276259Sgreen if (type == SSH2_MSG_NEWKEYS) 72376259Sgreen set_newkeys(MODE_OUT); 72460573Skris} 72560573Skris 72660573Skrisvoid 72792555Sdespacket_send(void) 72860573Skris{ 72992555Sdes if (compat20) 73060573Skris packet_send2(); 73160573Skris else 73260573Skris packet_send1(); 73360573Skris DBG(debug("packet_send done")); 73460573Skris} 73560573Skris 73660573Skris/* 73757429Smarkm * Waits until a packet has been received, and returns its type. Note that 73857429Smarkm * no other data is processed until this returns, so this function should not 73957429Smarkm * be used during the interactive session. 74057429Smarkm */ 74157429Smarkm 74257429Smarkmint 74392555Sdespacket_read_seqnr(u_int32_t *seqnr_p) 74457429Smarkm{ 74557429Smarkm int type, len; 74676259Sgreen fd_set *setp; 74757429Smarkm char buf[8192]; 74860573Skris DBG(debug("packet_read()")); 74957429Smarkm 75076259Sgreen setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) * 75176259Sgreen sizeof(fd_mask)); 75276259Sgreen 75357429Smarkm /* Since we are blocking, ensure that all written packets have been sent. */ 75457429Smarkm packet_write_wait(); 75557429Smarkm 75657429Smarkm /* Stay in the loop until we have received a complete packet. */ 75757429Smarkm for (;;) { 75857429Smarkm /* Try to read a packet from the buffer. */ 75992555Sdes type = packet_read_poll_seqnr(seqnr_p); 76092555Sdes if (!compat20 && ( 76160573Skris type == SSH_SMSG_SUCCESS 76257429Smarkm || type == SSH_SMSG_FAILURE 76357429Smarkm || type == SSH_CMSG_EOF 76460573Skris || type == SSH_CMSG_EXIT_CONFIRMATION)) 76592555Sdes packet_check_eom(); 76657429Smarkm /* If we got a packet, return it. */ 76776259Sgreen if (type != SSH_MSG_NONE) { 76876259Sgreen xfree(setp); 76957429Smarkm return type; 77076259Sgreen } 77157429Smarkm /* 77257429Smarkm * Otherwise, wait for some data to arrive, add it to the 77357429Smarkm * buffer, and try again. 77457429Smarkm */ 77576259Sgreen memset(setp, 0, howmany(connection_in + 1, NFDBITS) * 77676259Sgreen sizeof(fd_mask)); 77776259Sgreen FD_SET(connection_in, setp); 77857429Smarkm 77957429Smarkm /* Wait for some data to arrive. */ 78076259Sgreen while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && 78176259Sgreen (errno == EAGAIN || errno == EINTR)) 78276259Sgreen ; 78357429Smarkm 78457429Smarkm /* Read data from the socket. */ 78557429Smarkm len = read(connection_in, buf, sizeof(buf)); 78657429Smarkm if (len == 0) { 78757429Smarkm log("Connection closed by %.200s", get_remote_ipaddr()); 78857429Smarkm fatal_cleanup(); 78957429Smarkm } 79057429Smarkm if (len < 0) 79157429Smarkm fatal("Read from socket failed: %.100s", strerror(errno)); 79257429Smarkm /* Append it to the buffer. */ 79357429Smarkm packet_process_incoming(buf, len); 79457429Smarkm } 79557429Smarkm /* NOTREACHED */ 79657429Smarkm} 79757429Smarkm 79892555Sdesint 79992555Sdespacket_read(void) 80092555Sdes{ 80192555Sdes return packet_read_seqnr(NULL); 80292555Sdes} 80392555Sdes 80457429Smarkm/* 80557429Smarkm * Waits until a packet has been received, verifies that its type matches 80657429Smarkm * that given, and gives a fatal error and exits if there is a mismatch. 80757429Smarkm */ 80857429Smarkm 80957429Smarkmvoid 81092555Sdespacket_read_expect(int expected_type) 81157429Smarkm{ 81257429Smarkm int type; 81357429Smarkm 81492555Sdes type = packet_read(); 81557429Smarkm if (type != expected_type) 81657429Smarkm packet_disconnect("Protocol error: expected packet type %d, got %d", 81760573Skris expected_type, type); 81857429Smarkm} 81957429Smarkm 82057429Smarkm/* Checks if a full packet is available in the data received so far via 82157429Smarkm * packet_process_incoming. If so, reads the packet; otherwise returns 82257429Smarkm * SSH_MSG_NONE. This does not wait for data from the connection. 82357429Smarkm * 82457429Smarkm * SSH_MSG_DISCONNECT is handled specially here. Also, 82557429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned 82657429Smarkm * to higher levels. 82757429Smarkm */ 82857429Smarkm 82992555Sdesstatic int 83092555Sdespacket_read_poll1(void) 83157429Smarkm{ 83276259Sgreen u_int len, padded_len; 83392555Sdes u_char *cp, type; 83476259Sgreen u_int checksum, stored_checksum; 83557429Smarkm 83657429Smarkm /* Check if input size is less than minimum packet size. */ 83757429Smarkm if (buffer_len(&input) < 4 + 8) 83857429Smarkm return SSH_MSG_NONE; 83957429Smarkm /* Get length of incoming packet. */ 84092555Sdes cp = buffer_ptr(&input); 84192555Sdes len = GET_32BIT(cp); 84257429Smarkm if (len < 1 + 2 + 2 || len > 256 * 1024) 843113908Sdes packet_disconnect("Bad packet length %u.", len); 84457429Smarkm padded_len = (len + 8) & ~7; 84557429Smarkm 84657429Smarkm /* Check if the packet has been entirely received. */ 84757429Smarkm if (buffer_len(&input) < 4 + padded_len) 84857429Smarkm return SSH_MSG_NONE; 84957429Smarkm 85057429Smarkm /* The entire packet is in buffer. */ 85157429Smarkm 85257429Smarkm /* Consume packet length. */ 85357429Smarkm buffer_consume(&input, 4); 85457429Smarkm 85592555Sdes /* 85692555Sdes * Cryptographic attack detector for ssh 85792555Sdes * (C)1998 CORE-SDI, Buenos Aires Argentina 85892555Sdes * Ariel Futoransky(futo@core-sdi.com) 85992555Sdes */ 86092555Sdes if (!receive_context.plaintext && 86192555Sdes detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED) 86292555Sdes packet_disconnect("crc32 compensation attack: network attack detected"); 86392555Sdes 86492555Sdes /* Decrypt data to incoming_packet. */ 86557429Smarkm buffer_clear(&incoming_packet); 86692555Sdes cp = buffer_append_space(&incoming_packet, padded_len); 86792555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len); 86892555Sdes 86957429Smarkm buffer_consume(&input, padded_len); 87057429Smarkm 87157429Smarkm#ifdef PACKET_DEBUG 87257429Smarkm fprintf(stderr, "read_poll plain: "); 87357429Smarkm buffer_dump(&incoming_packet); 87457429Smarkm#endif 87557429Smarkm 87657429Smarkm /* Compute packet checksum. */ 87792555Sdes checksum = ssh_crc32(buffer_ptr(&incoming_packet), 87860573Skris buffer_len(&incoming_packet) - 4); 87957429Smarkm 88057429Smarkm /* Skip padding. */ 88157429Smarkm buffer_consume(&incoming_packet, 8 - len % 8); 88257429Smarkm 88357429Smarkm /* Test check bytes. */ 88457429Smarkm if (len != buffer_len(&incoming_packet)) 88592555Sdes packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 88660573Skris len, buffer_len(&incoming_packet)); 88757429Smarkm 88892555Sdes cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4; 88992555Sdes stored_checksum = GET_32BIT(cp); 89057429Smarkm if (checksum != stored_checksum) 89157429Smarkm packet_disconnect("Corrupted check bytes on input."); 89257429Smarkm buffer_consume_end(&incoming_packet, 4); 89357429Smarkm 89457429Smarkm if (packet_compression) { 89557429Smarkm buffer_clear(&compression_buffer); 89657429Smarkm buffer_uncompress(&incoming_packet, &compression_buffer); 89757429Smarkm buffer_clear(&incoming_packet); 89857429Smarkm buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 89960573Skris buffer_len(&compression_buffer)); 90057429Smarkm } 90192555Sdes type = buffer_get_char(&incoming_packet); 90292555Sdes return type; 90360573Skris} 90457429Smarkm 90592555Sdesstatic int 90692555Sdespacket_read_poll2(u_int32_t *seqnr_p) 90760573Skris{ 90876259Sgreen static u_int packet_length = 0; 90976259Sgreen u_int padlen, need; 91092555Sdes u_char *macbuf, *cp, type; 91160573Skris int maclen, block_size; 91260573Skris Enc *enc = NULL; 91360573Skris Mac *mac = NULL; 91460573Skris Comp *comp = NULL; 91557429Smarkm 91676259Sgreen if (newkeys[MODE_IN] != NULL) { 91776259Sgreen enc = &newkeys[MODE_IN]->enc; 91876259Sgreen mac = &newkeys[MODE_IN]->mac; 91976259Sgreen comp = &newkeys[MODE_IN]->comp; 92057429Smarkm } 92160573Skris maclen = mac && mac->enabled ? mac->mac_len : 0; 92292555Sdes block_size = enc ? enc->block_size : 8; 92360573Skris 92460573Skris if (packet_length == 0) { 92560573Skris /* 92660573Skris * check if input size is less than the cipher block size, 92760573Skris * decrypt first block and extract length of incoming packet 92860573Skris */ 92960573Skris if (buffer_len(&input) < block_size) 93060573Skris return SSH_MSG_NONE; 93160573Skris buffer_clear(&incoming_packet); 93292555Sdes cp = buffer_append_space(&incoming_packet, block_size); 93392555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), 93460573Skris block_size); 93592555Sdes cp = buffer_ptr(&incoming_packet); 93692555Sdes packet_length = GET_32BIT(cp); 93760573Skris if (packet_length < 1 + 4 || packet_length > 256 * 1024) { 93860573Skris buffer_dump(&incoming_packet); 939113908Sdes packet_disconnect("Bad packet length %u.", packet_length); 94060573Skris } 941113908Sdes DBG(debug("input: packet len %u", packet_length+4)); 94260573Skris buffer_consume(&input, block_size); 94360573Skris } 94460573Skris /* we have a partial packet of block_size bytes */ 94560573Skris need = 4 + packet_length - block_size; 94660573Skris DBG(debug("partial packet %d, need %d, maclen %d", block_size, 94760573Skris need, maclen)); 94860573Skris if (need % block_size != 0) 94960573Skris fatal("padding error: need %d block %d mod %d", 95060573Skris need, block_size, need % block_size); 95160573Skris /* 95260573Skris * check if the entire packet has been received and 95360573Skris * decrypt into incoming_packet 95460573Skris */ 95560573Skris if (buffer_len(&input) < need + maclen) 95660573Skris return SSH_MSG_NONE; 95760573Skris#ifdef PACKET_DEBUG 95860573Skris fprintf(stderr, "read_poll enc/full: "); 95960573Skris buffer_dump(&input); 96060573Skris#endif 96192555Sdes cp = buffer_append_space(&incoming_packet, need); 96292555Sdes cipher_crypt(&receive_context, cp, buffer_ptr(&input), need); 96360573Skris buffer_consume(&input, need); 96460573Skris /* 96560573Skris * compute MAC over seqnr and packet, 96660573Skris * increment sequence number for incoming packet 96760573Skris */ 96860573Skris if (mac && mac->enabled) { 96998675Sdes macbuf = mac_compute(mac, read_seqnr, 97092555Sdes buffer_ptr(&incoming_packet), 97176259Sgreen buffer_len(&incoming_packet)); 97260573Skris if (memcmp(macbuf, buffer_ptr(&input), mac->mac_len) != 0) 97369587Sgreen packet_disconnect("Corrupted MAC on input."); 97498675Sdes DBG(debug("MAC #%d ok", read_seqnr)); 97560573Skris buffer_consume(&input, mac->mac_len); 97660573Skris } 97792555Sdes if (seqnr_p != NULL) 97898675Sdes *seqnr_p = read_seqnr; 97998675Sdes if (++read_seqnr == 0) 98060573Skris log("incoming seqnr wraps around"); 98160573Skris 98260573Skris /* get padlen */ 98392555Sdes cp = buffer_ptr(&incoming_packet); 98492555Sdes padlen = cp[4]; 98560573Skris DBG(debug("input: padlen %d", padlen)); 98660573Skris if (padlen < 4) 98760573Skris packet_disconnect("Corrupted padlen %d on input.", padlen); 98860573Skris 98960573Skris /* skip packet size + padlen, discard padding */ 99060573Skris buffer_consume(&incoming_packet, 4 + 1); 99160573Skris buffer_consume_end(&incoming_packet, padlen); 99260573Skris 99360573Skris DBG(debug("input: len before de-compress %d", buffer_len(&incoming_packet))); 99460573Skris if (comp && comp->enabled) { 99560573Skris buffer_clear(&compression_buffer); 99660573Skris buffer_uncompress(&incoming_packet, &compression_buffer); 99760573Skris buffer_clear(&incoming_packet); 99860573Skris buffer_append(&incoming_packet, buffer_ptr(&compression_buffer), 99960573Skris buffer_len(&compression_buffer)); 1000106121Sdes DBG(debug("input: len after de-compress %d", 1001106121Sdes buffer_len(&incoming_packet))); 100260573Skris } 100360573Skris /* 100460573Skris * get packet type, implies consume. 100560573Skris * return length of payload (without type field) 100660573Skris */ 100792555Sdes type = buffer_get_char(&incoming_packet); 100876259Sgreen if (type == SSH2_MSG_NEWKEYS) 100976259Sgreen set_newkeys(MODE_IN); 101060573Skris#ifdef PACKET_DEBUG 101176259Sgreen fprintf(stderr, "read/plain[%d]:\r\n", type); 101260573Skris buffer_dump(&incoming_packet); 101360573Skris#endif 101492555Sdes /* reset for next packet */ 101592555Sdes packet_length = 0; 101692555Sdes return type; 101757429Smarkm} 101857429Smarkm 101960573Skrisint 102092555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p) 102160573Skris{ 102299060Sdes u_int reason, seqnr; 102392555Sdes u_char type; 102460573Skris char *msg; 102592555Sdes 102660573Skris for (;;) { 102792555Sdes if (compat20) { 102892555Sdes type = packet_read_poll2(seqnr_p); 102992555Sdes if (type) 103060573Skris DBG(debug("received packet type %d", type)); 103192555Sdes switch (type) { 103260573Skris case SSH2_MSG_IGNORE: 103360573Skris break; 103460573Skris case SSH2_MSG_DEBUG: 103560573Skris packet_get_char(); 103660573Skris msg = packet_get_string(NULL); 103760573Skris debug("Remote: %.900s", msg); 103860573Skris xfree(msg); 103960573Skris msg = packet_get_string(NULL); 104060573Skris xfree(msg); 104160573Skris break; 104260573Skris case SSH2_MSG_DISCONNECT: 104360573Skris reason = packet_get_int(); 104460573Skris msg = packet_get_string(NULL); 104599060Sdes log("Received disconnect from %s: %u: %.400s", 104699060Sdes get_remote_ipaddr(), reason, msg); 104760573Skris xfree(msg); 104860573Skris fatal_cleanup(); 104960573Skris break; 105092555Sdes case SSH2_MSG_UNIMPLEMENTED: 105192555Sdes seqnr = packet_get_int(); 105299060Sdes debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 105399060Sdes seqnr); 105492555Sdes break; 105560573Skris default: 105660573Skris return type; 105760573Skris break; 105876259Sgreen } 105960573Skris } else { 106092555Sdes type = packet_read_poll1(); 106192555Sdes switch (type) { 106260573Skris case SSH_MSG_IGNORE: 106360573Skris break; 106460573Skris case SSH_MSG_DEBUG: 106560573Skris msg = packet_get_string(NULL); 106660573Skris debug("Remote: %.900s", msg); 106760573Skris xfree(msg); 106860573Skris break; 106960573Skris case SSH_MSG_DISCONNECT: 107060573Skris msg = packet_get_string(NULL); 107199060Sdes log("Received disconnect from %s: %.400s", 107299060Sdes get_remote_ipaddr(), msg); 107360573Skris fatal_cleanup(); 107460573Skris xfree(msg); 107560573Skris break; 107660573Skris default: 107792555Sdes if (type) 107860573Skris DBG(debug("received packet type %d", type)); 107960573Skris return type; 108060573Skris break; 108176259Sgreen } 108260573Skris } 108360573Skris } 108460573Skris} 108560573Skris 108692555Sdesint 108792555Sdespacket_read_poll(void) 108892555Sdes{ 108992555Sdes return packet_read_poll_seqnr(NULL); 109092555Sdes} 109192555Sdes 109257429Smarkm/* 109357429Smarkm * Buffers the given amount of input characters. This is intended to be used 109457429Smarkm * together with packet_read_poll. 109557429Smarkm */ 109657429Smarkm 109757429Smarkmvoid 109876259Sgreenpacket_process_incoming(const char *buf, u_int len) 109957429Smarkm{ 110057429Smarkm buffer_append(&input, buf, len); 110157429Smarkm} 110257429Smarkm 110357429Smarkm/* Returns a character from the packet. */ 110457429Smarkm 110576259Sgreenu_int 110692555Sdespacket_get_char(void) 110757429Smarkm{ 110857429Smarkm char ch; 1109106121Sdes 111057429Smarkm buffer_get(&incoming_packet, &ch, 1); 111176259Sgreen return (u_char) ch; 111257429Smarkm} 111357429Smarkm 111457429Smarkm/* Returns an integer from the packet data. */ 111557429Smarkm 111676259Sgreenu_int 111792555Sdespacket_get_int(void) 111857429Smarkm{ 111957429Smarkm return buffer_get_int(&incoming_packet); 112057429Smarkm} 112157429Smarkm 112257429Smarkm/* 112357429Smarkm * Returns an arbitrary precision integer from the packet data. The integer 112457429Smarkm * must have been initialized before this call. 112557429Smarkm */ 112657429Smarkm 112757429Smarkmvoid 112892555Sdespacket_get_bignum(BIGNUM * value) 112957429Smarkm{ 113092555Sdes buffer_get_bignum(&incoming_packet, value); 113157429Smarkm} 113257429Smarkm 113360573Skrisvoid 113492555Sdespacket_get_bignum2(BIGNUM * value) 113560573Skris{ 113692555Sdes buffer_get_bignum2(&incoming_packet, value); 113760573Skris} 113860573Skris 113992555Sdesvoid * 114060573Skrispacket_get_raw(int *length_ptr) 114160573Skris{ 114260573Skris int bytes = buffer_len(&incoming_packet); 1143106121Sdes 114460573Skris if (length_ptr != NULL) 114560573Skris *length_ptr = bytes; 114660573Skris return buffer_ptr(&incoming_packet); 114760573Skris} 114860573Skris 114960573Skrisint 115060573Skrispacket_remaining(void) 115160573Skris{ 115260573Skris return buffer_len(&incoming_packet); 115360573Skris} 115460573Skris 115557429Smarkm/* 115657429Smarkm * Returns a string from the packet data. The string is allocated using 115757429Smarkm * xmalloc; it is the responsibility of the calling program to free it when 115857429Smarkm * no longer needed. The length_ptr argument may be NULL, or point to an 115957429Smarkm * integer into which the length of the string is stored. 116057429Smarkm */ 116157429Smarkm 116292555Sdesvoid * 116376259Sgreenpacket_get_string(u_int *length_ptr) 116457429Smarkm{ 116557429Smarkm return buffer_get_string(&incoming_packet, length_ptr); 116657429Smarkm} 116757429Smarkm 116857429Smarkm/* 116957429Smarkm * Sends a diagnostic message from the server to the client. This message 117057429Smarkm * can be sent at any time (but not while constructing another message). The 117157429Smarkm * message is printed immediately, but only if the client is being executed 117257429Smarkm * in verbose mode. These messages are primarily intended to ease debugging 117357429Smarkm * authentication problems. The length of the formatted message must not 117457429Smarkm * exceed 1024 bytes. This will automatically call packet_write_wait. 117557429Smarkm */ 117657429Smarkm 117757429Smarkmvoid 117857429Smarkmpacket_send_debug(const char *fmt,...) 117957429Smarkm{ 118057429Smarkm char buf[1024]; 118157429Smarkm va_list args; 118257429Smarkm 118376259Sgreen if (compat20 && (datafellows & SSH_BUG_DEBUG)) 118476259Sgreen return; 118576259Sgreen 118657429Smarkm va_start(args, fmt); 118757429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 118857429Smarkm va_end(args); 118957429Smarkm 119060573Skris if (compat20) { 119160573Skris packet_start(SSH2_MSG_DEBUG); 119260573Skris packet_put_char(0); /* bool: always display */ 119360573Skris packet_put_cstring(buf); 119460573Skris packet_put_cstring(""); 119560573Skris } else { 119660573Skris packet_start(SSH_MSG_DEBUG); 119760573Skris packet_put_cstring(buf); 119860573Skris } 119957429Smarkm packet_send(); 120057429Smarkm packet_write_wait(); 120157429Smarkm} 120257429Smarkm 120357429Smarkm/* 120457429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the 120557429Smarkm * connection, and exits. This function never returns. The error message 120657429Smarkm * should not contain a newline. The length of the formatted message must 120757429Smarkm * not exceed 1024 bytes. 120857429Smarkm */ 120957429Smarkm 121057429Smarkmvoid 121157429Smarkmpacket_disconnect(const char *fmt,...) 121257429Smarkm{ 121357429Smarkm char buf[1024]; 121457429Smarkm va_list args; 121557429Smarkm static int disconnecting = 0; 1216106121Sdes 121757429Smarkm if (disconnecting) /* Guard against recursive invocations. */ 121857429Smarkm fatal("packet_disconnect called recursively."); 121957429Smarkm disconnecting = 1; 122057429Smarkm 122157429Smarkm /* 122257429Smarkm * Format the message. Note that the caller must make sure the 122357429Smarkm * message is of limited size. 122457429Smarkm */ 122557429Smarkm va_start(args, fmt); 122657429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 122757429Smarkm va_end(args); 122857429Smarkm 1229113908Sdes /* Display the error locally */ 1230113908Sdes log("Disconnecting: %.100s", buf); 1231113908Sdes 123257429Smarkm /* Send the disconnect message to the other side, and wait for it to get sent. */ 123360573Skris if (compat20) { 123460573Skris packet_start(SSH2_MSG_DISCONNECT); 123560573Skris packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 123660573Skris packet_put_cstring(buf); 123760573Skris packet_put_cstring(""); 123860573Skris } else { 123960573Skris packet_start(SSH_MSG_DISCONNECT); 124092555Sdes packet_put_cstring(buf); 124160573Skris } 124257429Smarkm packet_send(); 124357429Smarkm packet_write_wait(); 124457429Smarkm 124557429Smarkm /* Stop listening for connections. */ 124692555Sdes channel_close_all(); 124757429Smarkm 124857429Smarkm /* Close the connection. */ 124957429Smarkm packet_close(); 125057429Smarkm 125157429Smarkm fatal_cleanup(); 125257429Smarkm} 125357429Smarkm 125457429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */ 125557429Smarkm 125657429Smarkmvoid 125792555Sdespacket_write_poll(void) 125857429Smarkm{ 125957429Smarkm int len = buffer_len(&output); 1260106121Sdes 126157429Smarkm if (len > 0) { 126257429Smarkm len = write(connection_out, buffer_ptr(&output), len); 126357429Smarkm if (len <= 0) { 126457429Smarkm if (errno == EAGAIN) 126557429Smarkm return; 126657429Smarkm else 126757429Smarkm fatal("Write failed: %.100s", strerror(errno)); 126857429Smarkm } 126957429Smarkm buffer_consume(&output, len); 127057429Smarkm } 127157429Smarkm} 127257429Smarkm 127357429Smarkm/* 127457429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been 127557429Smarkm * written. 127657429Smarkm */ 127757429Smarkm 127857429Smarkmvoid 127992555Sdespacket_write_wait(void) 128057429Smarkm{ 128176259Sgreen fd_set *setp; 128276259Sgreen 128376259Sgreen setp = (fd_set *)xmalloc(howmany(connection_out + 1, NFDBITS) * 128476259Sgreen sizeof(fd_mask)); 128557429Smarkm packet_write_poll(); 128657429Smarkm while (packet_have_data_to_write()) { 128776259Sgreen memset(setp, 0, howmany(connection_out + 1, NFDBITS) * 128876259Sgreen sizeof(fd_mask)); 128976259Sgreen FD_SET(connection_out, setp); 129076259Sgreen while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && 129176259Sgreen (errno == EAGAIN || errno == EINTR)) 129276259Sgreen ; 129357429Smarkm packet_write_poll(); 129457429Smarkm } 129576259Sgreen xfree(setp); 129657429Smarkm} 129757429Smarkm 129857429Smarkm/* Returns true if there is buffered data to write to the connection. */ 129957429Smarkm 130057429Smarkmint 130192555Sdespacket_have_data_to_write(void) 130257429Smarkm{ 130357429Smarkm return buffer_len(&output) != 0; 130457429Smarkm} 130557429Smarkm 130657429Smarkm/* Returns true if there is not too much data to write to the connection. */ 130757429Smarkm 130857429Smarkmint 130992555Sdespacket_not_very_much_data_to_write(void) 131057429Smarkm{ 131157429Smarkm if (interactive_mode) 131257429Smarkm return buffer_len(&output) < 16384; 131357429Smarkm else 131457429Smarkm return buffer_len(&output) < 128 * 1024; 131557429Smarkm} 131657429Smarkm 1317113908Sdesstatic void 1318113908Sdespacket_set_tos(int interactive) 1319113908Sdes{ 1320113908Sdes int tos = interactive ? IPTOS_LOWDELAY : IPTOS_THROUGHPUT; 1321113908Sdes 1322113908Sdes if (!packet_connection_is_on_socket() || 1323113908Sdes !packet_connection_is_ipv4()) 1324113908Sdes return; 1325113908Sdes if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, &tos, 1326113908Sdes sizeof(tos)) < 0) 1327113908Sdes error("setsockopt IP_TOS %d: %.100s:", 1328113908Sdes tos, strerror(errno)); 1329113908Sdes} 1330113908Sdes 133157429Smarkm/* Informs that the current session is interactive. Sets IP flags for that. */ 133257429Smarkm 133357429Smarkmvoid 133476259Sgreenpacket_set_interactive(int interactive) 133557429Smarkm{ 133676259Sgreen static int called = 0; 133757429Smarkm 133876259Sgreen if (called) 133976259Sgreen return; 134076259Sgreen called = 1; 134176259Sgreen 134257429Smarkm /* Record that we are in interactive mode. */ 134357429Smarkm interactive_mode = interactive; 134457429Smarkm 134557429Smarkm /* Only set socket options if using a socket. */ 134657429Smarkm if (!packet_connection_is_on_socket()) 1347113908Sdes if (interactive) 134892555Sdes set_nodelay(connection_in); 134998937Sdes#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN) 1350113908Sdes packet_set_tos(interactive); 135198937Sdes#endif 1352113908Sdes 135357429Smarkm} 135457429Smarkm 135557429Smarkm/* Returns true if the current connection is interactive. */ 135657429Smarkm 135757429Smarkmint 135892555Sdespacket_is_interactive(void) 135957429Smarkm{ 136057429Smarkm return interactive_mode; 136157429Smarkm} 136257429Smarkm 136357429Smarkmint 136457429Smarkmpacket_set_maxsize(int s) 136557429Smarkm{ 136657429Smarkm static int called = 0; 1367106121Sdes 136857429Smarkm if (called) { 136960573Skris log("packet_set_maxsize: called twice: old %d new %d", 137060573Skris max_packet_size, s); 137157429Smarkm return -1; 137257429Smarkm } 137357429Smarkm if (s < 4 * 1024 || s > 1024 * 1024) { 137457429Smarkm log("packet_set_maxsize: bad size %d", s); 137557429Smarkm return -1; 137657429Smarkm } 137792555Sdes called = 1; 137892555Sdes debug("packet_set_maxsize: setting to %d", s); 137957429Smarkm max_packet_size = s; 138057429Smarkm return s; 138157429Smarkm} 138276259Sgreen 138392555Sdes/* roundup current message to pad bytes */ 138492555Sdesvoid 138592555Sdespacket_add_padding(u_char pad) 138692555Sdes{ 138792555Sdes extra_pad = pad; 138892555Sdes} 138992555Sdes 139076259Sgreen/* 139176259Sgreen * 9.2. Ignored Data Message 139276259Sgreen * 139376259Sgreen * byte SSH_MSG_IGNORE 139476259Sgreen * string data 139576259Sgreen * 139676259Sgreen * All implementations MUST understand (and ignore) this message at any 139776259Sgreen * time (after receiving the protocol version). No implementation is 139876259Sgreen * required to send them. This message can be used as an additional 139976259Sgreen * protection measure against advanced traffic analysis techniques. 140076259Sgreen */ 140176259Sgreenvoid 140276259Sgreenpacket_send_ignore(int nbytes) 140376259Sgreen{ 140476259Sgreen u_int32_t rand = 0; 140576259Sgreen int i; 140676259Sgreen 140776259Sgreen packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 140876259Sgreen packet_put_int(nbytes); 140992555Sdes for (i = 0; i < nbytes; i++) { 141076259Sgreen if (i % 4 == 0) 141176259Sgreen rand = arc4random(); 141276259Sgreen packet_put_char(rand & 0xff); 141376259Sgreen rand >>= 8; 141476259Sgreen } 141576259Sgreen} 1416