1264377Sdes/* $OpenBSD: packet.c,v 1.192 2014/02/02 03:44:31 djm Exp $ */ 257429Smarkm/* 357429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 557429Smarkm * All rights reserved 657429Smarkm * This file contains code implementing the packet protocol and communication 757429Smarkm * with the other side. This same code is used both on client and server side. 860573Skris * 965668Skris * As far as I am concerned, the code I have written for this software 1065668Skris * can be used freely for any purpose. Any derived versions of this 1165668Skris * software must be clearly marked as such, and if the derived work is 1265668Skris * incompatible with the protocol description in the RFC file, it must be 1365668Skris * called by a name other than "ssh" or "Secure Shell". 1465668Skris * 1565668Skris * 1660573Skris * SSH2 packet format added by Markus Friedl. 1792555Sdes * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 1860573Skris * 1965668Skris * Redistribution and use in source and binary forms, with or without 2065668Skris * modification, are permitted provided that the following conditions 2165668Skris * are met: 2265668Skris * 1. Redistributions of source code must retain the above copyright 2365668Skris * notice, this list of conditions and the following disclaimer. 2465668Skris * 2. Redistributions in binary form must reproduce the above copyright 2565668Skris * notice, this list of conditions and the following disclaimer in the 2665668Skris * documentation and/or other materials provided with the distribution. 2765668Skris * 2865668Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2965668Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 3065668Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 3165668Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 3265668Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 3365668Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3465668Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3565668Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3665668Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3765668Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3857429Smarkm */ 3957429Smarkm 4057429Smarkm#include "includes.h" 41162852Sdes 42162852Sdes#include <sys/types.h> 43124208Sdes#include "openbsd-compat/sys-queue.h" 44162852Sdes#include <sys/param.h> 45162852Sdes#include <sys/socket.h> 46162852Sdes#ifdef HAVE_SYS_TIME_H 47162852Sdes# include <sys/time.h> 48162852Sdes#endif 49124208Sdes 50162852Sdes#include <netinet/in.h> 51162852Sdes#include <netinet/ip.h> 52162852Sdes#include <arpa/inet.h> 53162852Sdes 54162852Sdes#include <errno.h> 55162852Sdes#include <stdarg.h> 56162852Sdes#include <stdio.h> 57162852Sdes#include <stdlib.h> 58162852Sdes#include <string.h> 59162852Sdes#include <unistd.h> 60162852Sdes#include <signal.h> 61255767Sdes#include <time.h> 62162852Sdes 6357429Smarkm#include "xmalloc.h" 6457429Smarkm#include "buffer.h" 6557429Smarkm#include "packet.h" 6657429Smarkm#include "crc32.h" 6757429Smarkm#include "compress.h" 6857429Smarkm#include "deattack.h" 6960573Skris#include "channels.h" 7060573Skris#include "compat.h" 7176259Sgreen#include "ssh1.h" 7260573Skris#include "ssh2.h" 7369587Sgreen#include "cipher.h" 74162852Sdes#include "key.h" 7560573Skris#include "kex.h" 7676259Sgreen#include "mac.h" 7776259Sgreen#include "log.h" 7876259Sgreen#include "canohost.h" 7992555Sdes#include "misc.h" 8098675Sdes#include "ssh.h" 81197679Sdes#include "roaming.h" 8260573Skris 8360573Skris#ifdef PACKET_DEBUG 8460573Skris#define DBG(x) x 8560573Skris#else 8660573Skris#define DBG(x) 8760573Skris#endif 8860573Skris 89192595Sdes#define PACKET_MAX_SIZE (256 * 1024) 90192595Sdes 91197679Sdesstruct packet_state { 92197679Sdes u_int32_t seqnr; 93197679Sdes u_int32_t packets; 94197679Sdes u_int64_t blocks; 95197679Sdes u_int64_t bytes; 96197679Sdes}; 9757429Smarkm 98197679Sdesstruct packet { 99197679Sdes TAILQ_ENTRY(packet) next; 100197679Sdes u_char type; 101197679Sdes Buffer payload; 102197679Sdes}; 10357429Smarkm 104197679Sdesstruct session_state { 105197679Sdes /* 106197679Sdes * This variable contains the file descriptors used for 107197679Sdes * communicating with the other side. connection_in is used for 108197679Sdes * reading; connection_out for writing. These can be the same 109197679Sdes * descriptor, in which case it is assumed to be a socket. 110197679Sdes */ 111197679Sdes int connection_in; 112197679Sdes int connection_out; 11357429Smarkm 114197679Sdes /* Protocol flags for the remote side. */ 115197679Sdes u_int remote_protocol_flags; 11657429Smarkm 117197679Sdes /* Encryption context for receiving data. Only used for decryption. */ 118197679Sdes CipherContext receive_context; 11957429Smarkm 120197679Sdes /* Encryption context for sending data. Only used for encryption. */ 121197679Sdes CipherContext send_context; 12257429Smarkm 123197679Sdes /* Buffer for raw input data from the socket. */ 124197679Sdes Buffer input; 12557429Smarkm 126197679Sdes /* Buffer for raw output data going to the socket. */ 127197679Sdes Buffer output; 12857429Smarkm 129197679Sdes /* Buffer for the partial outgoing packet being constructed. */ 130197679Sdes Buffer outgoing_packet; 13157429Smarkm 132197679Sdes /* Buffer for the incoming packet currently being processed. */ 133197679Sdes Buffer incoming_packet; 13457429Smarkm 135197679Sdes /* Scratch buffer for packet compression/decompression. */ 136197679Sdes Buffer compression_buffer; 137197679Sdes int compression_buffer_ready; 13857429Smarkm 139197679Sdes /* 140197679Sdes * Flag indicating whether packet compression/decompression is 141197679Sdes * enabled. 142197679Sdes */ 143197679Sdes int packet_compression; 14457429Smarkm 145197679Sdes /* default maximum packet size */ 146197679Sdes u_int max_packet_size; 14757429Smarkm 148197679Sdes /* Flag indicating whether this module has been initialized. */ 149197679Sdes int initialized; 150149749Sdes 151197679Sdes /* Set to true if the connection is interactive. */ 152197679Sdes int interactive_mode; 153149749Sdes 154197679Sdes /* Set to true if we are the server side. */ 155197679Sdes int server_side; 156181111Sdes 157197679Sdes /* Set to true if we are authenticated. */ 158197679Sdes int after_authentication; 159181111Sdes 160197679Sdes int keep_alive_timeouts; 16160573Skris 162197679Sdes /* The maximum time that we will wait to send or receive a packet */ 163197679Sdes int packet_timeout_ms; 164124208Sdes 165197679Sdes /* Session key information for Encryption and MAC */ 166197679Sdes Newkeys *newkeys[MODE_MAX]; 167197679Sdes struct packet_state p_read, p_send; 16898675Sdes 169255767Sdes /* Volume-based rekeying */ 170197679Sdes u_int64_t max_blocks_in, max_blocks_out; 171197679Sdes u_int32_t rekey_limit; 17260573Skris 173255767Sdes /* Time-based rekeying */ 174255767Sdes time_t rekey_interval; /* how often in seconds */ 175255767Sdes time_t rekey_time; /* time of last rekeying */ 176255767Sdes 177197679Sdes /* Session key for protocol v1 */ 178197679Sdes u_char ssh1_key[SSH_SESSION_KEY_LENGTH]; 179197679Sdes u_int ssh1_keylen; 180192595Sdes 181197679Sdes /* roundup current message to extra_pad bytes */ 182197679Sdes u_char extra_pad; 183197679Sdes 184197679Sdes /* XXX discard incoming data after MAC error */ 185197679Sdes u_int packet_discard; 186197679Sdes Mac *packet_discard_mac; 187197679Sdes 188197679Sdes /* Used in packet_read_poll2() */ 189197679Sdes u_int packlen; 190197679Sdes 191197679Sdes /* Used in packet_send2 */ 192197679Sdes int rekeying; 193197679Sdes 194197679Sdes /* Used in packet_set_interactive */ 195197679Sdes int set_interactive_called; 196197679Sdes 197197679Sdes /* Used in packet_set_maxsize */ 198197679Sdes int set_maxsize_called; 199197679Sdes 200197679Sdes TAILQ_HEAD(, packet) outgoing; 201124208Sdes}; 202124208Sdes 203197679Sdesstatic struct session_state *active_state, *backup_state; 204224638Sbrooks#ifdef NONE_CIPHER_ENABLED 205224638Sbrooksstatic int rekey_requested = 0; 206224638Sbrooks#endif 207197679Sdes 208197679Sdesstatic struct session_state * 209197679Sdesalloc_session_state(void) 210197679Sdes{ 211221420Sdes struct session_state *s = xcalloc(1, sizeof(*s)); 212197679Sdes 213221420Sdes s->connection_in = -1; 214221420Sdes s->connection_out = -1; 215221420Sdes s->max_packet_size = 32768; 216221420Sdes s->packet_timeout_ms = -1; 217221420Sdes return s; 218197679Sdes} 219197679Sdes 22057429Smarkm/* 22157429Smarkm * Sets the descriptors used for communication. Disables encryption until 22257429Smarkm * packet_set_encryption_key is called. 22357429Smarkm */ 22457429Smarkmvoid 22557429Smarkmpacket_set_connection(int fd_in, int fd_out) 22657429Smarkm{ 227255767Sdes const Cipher *none = cipher_by_name("none"); 228106121Sdes 22969587Sgreen if (none == NULL) 23069587Sgreen fatal("packet_set_connection: cannot load cipher 'none'"); 231197679Sdes if (active_state == NULL) 232197679Sdes active_state = alloc_session_state(); 233197679Sdes active_state->connection_in = fd_in; 234197679Sdes active_state->connection_out = fd_out; 235197679Sdes cipher_init(&active_state->send_context, none, (const u_char *)"", 236137015Sdes 0, NULL, 0, CIPHER_ENCRYPT); 237197679Sdes cipher_init(&active_state->receive_context, none, (const u_char *)"", 238137015Sdes 0, NULL, 0, CIPHER_DECRYPT); 239197679Sdes active_state->newkeys[MODE_IN] = active_state->newkeys[MODE_OUT] = NULL; 240197679Sdes if (!active_state->initialized) { 241197679Sdes active_state->initialized = 1; 242197679Sdes buffer_init(&active_state->input); 243197679Sdes buffer_init(&active_state->output); 244197679Sdes buffer_init(&active_state->outgoing_packet); 245197679Sdes buffer_init(&active_state->incoming_packet); 246197679Sdes TAILQ_INIT(&active_state->outgoing); 247197679Sdes active_state->p_send.packets = active_state->p_read.packets = 0; 24857429Smarkm } 24957429Smarkm} 25057429Smarkm 251181111Sdesvoid 252181111Sdespacket_set_timeout(int timeout, int count) 253181111Sdes{ 254240075Sdes if (timeout <= 0 || count <= 0) { 255197679Sdes active_state->packet_timeout_ms = -1; 256181111Sdes return; 257181111Sdes } 258181111Sdes if ((INT_MAX / 1000) / count < timeout) 259197679Sdes active_state->packet_timeout_ms = INT_MAX; 260181111Sdes else 261197679Sdes active_state->packet_timeout_ms = timeout * count * 1000; 262181111Sdes} 263181111Sdes 264192595Sdesstatic void 265192595Sdespacket_stop_discard(void) 266192595Sdes{ 267197679Sdes if (active_state->packet_discard_mac) { 268192595Sdes char buf[1024]; 269192595Sdes 270192595Sdes memset(buf, 'a', sizeof(buf)); 271197679Sdes while (buffer_len(&active_state->incoming_packet) < 272197679Sdes PACKET_MAX_SIZE) 273197679Sdes buffer_append(&active_state->incoming_packet, buf, 274197679Sdes sizeof(buf)); 275197679Sdes (void) mac_compute(active_state->packet_discard_mac, 276197679Sdes active_state->p_read.seqnr, 277197679Sdes buffer_ptr(&active_state->incoming_packet), 278192595Sdes PACKET_MAX_SIZE); 279192595Sdes } 280192595Sdes logit("Finished discarding for %.200s", get_remote_ipaddr()); 281192595Sdes cleanup_exit(255); 282192595Sdes} 283192595Sdes 284192595Sdesstatic void 285192595Sdespacket_start_discard(Enc *enc, Mac *mac, u_int packet_length, u_int discard) 286192595Sdes{ 287248619Sdes if (enc == NULL || !cipher_is_cbc(enc->cipher) || (mac && mac->etm)) 288192595Sdes packet_disconnect("Packet corrupt"); 289192595Sdes if (packet_length != PACKET_MAX_SIZE && mac && mac->enabled) 290197679Sdes active_state->packet_discard_mac = mac; 291197679Sdes if (buffer_len(&active_state->input) >= discard) 292192595Sdes packet_stop_discard(); 293197679Sdes active_state->packet_discard = discard - 294197679Sdes buffer_len(&active_state->input); 295192595Sdes} 296192595Sdes 29757429Smarkm/* Returns 1 if remote host is connected via socket, 0 if not. */ 29857429Smarkm 29957429Smarkmint 30092555Sdespacket_connection_is_on_socket(void) 30157429Smarkm{ 30257429Smarkm struct sockaddr_storage from, to; 30357429Smarkm socklen_t fromlen, tolen; 30457429Smarkm 30557429Smarkm /* filedescriptors in and out are the same, so it's a socket */ 306197679Sdes if (active_state->connection_in == active_state->connection_out) 30757429Smarkm return 1; 30857429Smarkm fromlen = sizeof(from); 30957429Smarkm memset(&from, 0, sizeof(from)); 310197679Sdes if (getpeername(active_state->connection_in, (struct sockaddr *)&from, 311197679Sdes &fromlen) < 0) 31257429Smarkm return 0; 31357429Smarkm tolen = sizeof(to); 31457429Smarkm memset(&to, 0, sizeof(to)); 315197679Sdes if (getpeername(active_state->connection_out, (struct sockaddr *)&to, 316197679Sdes &tolen) < 0) 31757429Smarkm return 0; 31857429Smarkm if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0) 31957429Smarkm return 0; 32057429Smarkm if (from.ss_family != AF_INET && from.ss_family != AF_INET6) 32157429Smarkm return 0; 32257429Smarkm return 1; 32357429Smarkm} 32457429Smarkm 32598675Sdes/* 32698675Sdes * Exports an IV from the CipherContext required to export the key 32798675Sdes * state back from the unprivileged child to the privileged parent 32898675Sdes * process. 32998675Sdes */ 33098675Sdes 33198675Sdesvoid 33298675Sdespacket_get_keyiv(int mode, u_char *iv, u_int len) 33398675Sdes{ 33498675Sdes CipherContext *cc; 33598675Sdes 33698675Sdes if (mode == MODE_OUT) 337197679Sdes cc = &active_state->send_context; 33898675Sdes else 339197679Sdes cc = &active_state->receive_context; 34098675Sdes 34198675Sdes cipher_get_keyiv(cc, iv, len); 34298675Sdes} 34398675Sdes 34498675Sdesint 34598675Sdespacket_get_keycontext(int mode, u_char *dat) 34698675Sdes{ 34798675Sdes CipherContext *cc; 34898675Sdes 34998675Sdes if (mode == MODE_OUT) 350197679Sdes cc = &active_state->send_context; 35198675Sdes else 352197679Sdes cc = &active_state->receive_context; 35398675Sdes 35498675Sdes return (cipher_get_keycontext(cc, dat)); 35598675Sdes} 35698675Sdes 35798675Sdesvoid 35898675Sdespacket_set_keycontext(int mode, u_char *dat) 35998675Sdes{ 36098675Sdes CipherContext *cc; 36198675Sdes 36298675Sdes if (mode == MODE_OUT) 363197679Sdes cc = &active_state->send_context; 36498675Sdes else 365197679Sdes cc = &active_state->receive_context; 36698675Sdes 36798675Sdes cipher_set_keycontext(cc, dat); 36898675Sdes} 36998675Sdes 37098675Sdesint 37198675Sdespacket_get_keyiv_len(int mode) 37298675Sdes{ 37398675Sdes CipherContext *cc; 37498675Sdes 37598675Sdes if (mode == MODE_OUT) 376197679Sdes cc = &active_state->send_context; 37798675Sdes else 378197679Sdes cc = &active_state->receive_context; 37998675Sdes 38098675Sdes return (cipher_get_keyiv_len(cc)); 38198675Sdes} 382162852Sdes 38398675Sdesvoid 38498675Sdespacket_set_iv(int mode, u_char *dat) 38598675Sdes{ 38698675Sdes CipherContext *cc; 38798675Sdes 38898675Sdes if (mode == MODE_OUT) 389197679Sdes cc = &active_state->send_context; 39098675Sdes else 391197679Sdes cc = &active_state->receive_context; 39298675Sdes 39398675Sdes cipher_set_keyiv(cc, dat); 39498675Sdes} 395162852Sdes 39698675Sdesint 397124208Sdespacket_get_ssh1_cipher(void) 39898675Sdes{ 399197679Sdes return (cipher_get_number(active_state->receive_context.cipher)); 40098675Sdes} 40198675Sdes 402124208Sdesvoid 403221420Sdespacket_get_state(int mode, u_int32_t *seqnr, u_int64_t *blocks, 404221420Sdes u_int32_t *packets, u_int64_t *bytes) 405124208Sdes{ 406124208Sdes struct packet_state *state; 40798675Sdes 408197679Sdes state = (mode == MODE_IN) ? 409197679Sdes &active_state->p_read : &active_state->p_send; 410181111Sdes if (seqnr) 411181111Sdes *seqnr = state->seqnr; 412181111Sdes if (blocks) 413181111Sdes *blocks = state->blocks; 414181111Sdes if (packets) 415181111Sdes *packets = state->packets; 416181111Sdes if (bytes) 417181111Sdes *bytes = state->bytes; 41898675Sdes} 41998675Sdes 42098675Sdesvoid 421181111Sdespacket_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets, 422181111Sdes u_int64_t bytes) 42398675Sdes{ 424124208Sdes struct packet_state *state; 425124208Sdes 426197679Sdes state = (mode == MODE_IN) ? 427197679Sdes &active_state->p_read : &active_state->p_send; 428124208Sdes state->seqnr = seqnr; 429124208Sdes state->blocks = blocks; 430124208Sdes state->packets = packets; 431181111Sdes state->bytes = bytes; 43298675Sdes} 43398675Sdes 434226046Sdesstatic int 435226046Sdespacket_connection_af(void) 43657429Smarkm{ 43757429Smarkm struct sockaddr_storage to; 43857429Smarkm socklen_t tolen = sizeof(to); 43957429Smarkm 44057429Smarkm memset(&to, 0, sizeof(to)); 441197679Sdes if (getsockname(active_state->connection_out, (struct sockaddr *)&to, 442197679Sdes &tolen) < 0) 44357429Smarkm return 0; 44498937Sdes#ifdef IPV4_IN_IPV6 445126274Sdes if (to.ss_family == AF_INET6 && 44698937Sdes IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr)) 447226046Sdes return AF_INET; 44898937Sdes#endif 449226046Sdes return to.ss_family; 45057429Smarkm} 45157429Smarkm 45257429Smarkm/* Sets the connection into non-blocking mode. */ 45357429Smarkm 45457429Smarkmvoid 45592555Sdespacket_set_nonblocking(void) 45657429Smarkm{ 45757429Smarkm /* Set the socket into non-blocking mode. */ 458197679Sdes set_nonblock(active_state->connection_in); 45957429Smarkm 460197679Sdes if (active_state->connection_out != active_state->connection_in) 461197679Sdes set_nonblock(active_state->connection_out); 46257429Smarkm} 46357429Smarkm 46457429Smarkm/* Returns the socket used for reading. */ 46557429Smarkm 46657429Smarkmint 46792555Sdespacket_get_connection_in(void) 46857429Smarkm{ 469197679Sdes return active_state->connection_in; 47057429Smarkm} 47157429Smarkm 47257429Smarkm/* Returns the descriptor used for writing. */ 47357429Smarkm 47457429Smarkmint 47592555Sdespacket_get_connection_out(void) 47657429Smarkm{ 477197679Sdes return active_state->connection_out; 47857429Smarkm} 47957429Smarkm 48057429Smarkm/* Closes the connection and clears and frees internal data structures. */ 48157429Smarkm 48257429Smarkmvoid 48392555Sdespacket_close(void) 48457429Smarkm{ 485197679Sdes if (!active_state->initialized) 48657429Smarkm return; 487197679Sdes active_state->initialized = 0; 488197679Sdes if (active_state->connection_in == active_state->connection_out) { 489197679Sdes shutdown(active_state->connection_out, SHUT_RDWR); 490197679Sdes close(active_state->connection_out); 49157429Smarkm } else { 492197679Sdes close(active_state->connection_in); 493197679Sdes close(active_state->connection_out); 49457429Smarkm } 495197679Sdes buffer_free(&active_state->input); 496197679Sdes buffer_free(&active_state->output); 497197679Sdes buffer_free(&active_state->outgoing_packet); 498197679Sdes buffer_free(&active_state->incoming_packet); 499197679Sdes if (active_state->compression_buffer_ready) { 500197679Sdes buffer_free(&active_state->compression_buffer); 50157429Smarkm buffer_compress_uninit(); 50257429Smarkm } 503197679Sdes cipher_cleanup(&active_state->send_context); 504197679Sdes cipher_cleanup(&active_state->receive_context); 50557429Smarkm} 50657429Smarkm 50757429Smarkm/* Sets remote side protocol flags. */ 50857429Smarkm 50957429Smarkmvoid 51076259Sgreenpacket_set_protocol_flags(u_int protocol_flags) 51157429Smarkm{ 512197679Sdes active_state->remote_protocol_flags = protocol_flags; 51357429Smarkm} 51457429Smarkm 51557429Smarkm/* Returns the remote protocol flags set earlier by the above function. */ 51657429Smarkm 51776259Sgreenu_int 51892555Sdespacket_get_protocol_flags(void) 51957429Smarkm{ 520197679Sdes return active_state->remote_protocol_flags; 52157429Smarkm} 52257429Smarkm 52357429Smarkm/* 52457429Smarkm * Starts packet compression from the next packet on in both directions. 52557429Smarkm * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. 52657429Smarkm */ 52757429Smarkm 52892555Sdesstatic void 52992555Sdespacket_init_compression(void) 53076259Sgreen{ 531197679Sdes if (active_state->compression_buffer_ready == 1) 53276259Sgreen return; 533197679Sdes active_state->compression_buffer_ready = 1; 534197679Sdes buffer_init(&active_state->compression_buffer); 53576259Sgreen} 53676259Sgreen 53776259Sgreenvoid 53857429Smarkmpacket_start_compression(int level) 53957429Smarkm{ 540197679Sdes if (active_state->packet_compression && !compat20) 54157429Smarkm fatal("Compression already enabled."); 542197679Sdes active_state->packet_compression = 1; 54376259Sgreen packet_init_compression(); 54476259Sgreen buffer_compress_init_send(level); 54576259Sgreen buffer_compress_init_recv(); 54657429Smarkm} 54757429Smarkm 54857429Smarkm/* 54957429Smarkm * Causes any further packets to be encrypted using the given key. The same 55057429Smarkm * key is used for both sending and reception. However, both directions are 55157429Smarkm * encrypted independently of each other. 55257429Smarkm */ 55398675Sdes 55457429Smarkmvoid 555221420Sdespacket_set_encryption_key(const u_char *key, u_int keylen, int number) 55657429Smarkm{ 557255767Sdes const Cipher *cipher = cipher_by_number(number); 558106121Sdes 55969587Sgreen if (cipher == NULL) 56069587Sgreen fatal("packet_set_encryption_key: unknown cipher number %d", number); 56160573Skris if (keylen < 20) 56269587Sgreen fatal("packet_set_encryption_key: keylen too small: %d", keylen); 56398675Sdes if (keylen > SSH_SESSION_KEY_LENGTH) 56498675Sdes fatal("packet_set_encryption_key: keylen too big: %d", keylen); 565197679Sdes memcpy(active_state->ssh1_key, key, keylen); 566197679Sdes active_state->ssh1_keylen = keylen; 567197679Sdes cipher_init(&active_state->send_context, cipher, key, keylen, NULL, 568197679Sdes 0, CIPHER_ENCRYPT); 569197679Sdes cipher_init(&active_state->receive_context, cipher, key, keylen, NULL, 570197679Sdes 0, CIPHER_DECRYPT); 57157429Smarkm} 57257429Smarkm 57398675Sdesu_int 57498675Sdespacket_get_encryption_key(u_char *key) 57598675Sdes{ 57698675Sdes if (key == NULL) 577197679Sdes return (active_state->ssh1_keylen); 578197679Sdes memcpy(key, active_state->ssh1_key, active_state->ssh1_keylen); 579197679Sdes return (active_state->ssh1_keylen); 58098675Sdes} 58198675Sdes 58292555Sdes/* Start constructing a packet to send. */ 58357429Smarkmvoid 58492555Sdespacket_start(u_char type) 58557429Smarkm{ 58692555Sdes u_char buf[9]; 58792555Sdes int len; 58857429Smarkm 58992555Sdes DBG(debug("packet_start[%d]", type)); 59092555Sdes len = compat20 ? 6 : 9; 59192555Sdes memset(buf, 0, len - 1); 59292555Sdes buf[len - 1] = type; 593197679Sdes buffer_clear(&active_state->outgoing_packet); 594197679Sdes buffer_append(&active_state->outgoing_packet, buf, len); 59557429Smarkm} 59657429Smarkm 59792555Sdes/* Append payload. */ 59860573Skrisvoid 59957429Smarkmpacket_put_char(int value) 60057429Smarkm{ 60157429Smarkm char ch = value; 602106121Sdes 603197679Sdes buffer_append(&active_state->outgoing_packet, &ch, 1); 60457429Smarkm} 605162852Sdes 60657429Smarkmvoid 60776259Sgreenpacket_put_int(u_int value) 60857429Smarkm{ 609197679Sdes buffer_put_int(&active_state->outgoing_packet, value); 61057429Smarkm} 611162852Sdes 61257429Smarkmvoid 613197679Sdespacket_put_int64(u_int64_t value) 614197679Sdes{ 615197679Sdes buffer_put_int64(&active_state->outgoing_packet, value); 616197679Sdes} 617197679Sdes 618197679Sdesvoid 61992555Sdespacket_put_string(const void *buf, u_int len) 62057429Smarkm{ 621197679Sdes buffer_put_string(&active_state->outgoing_packet, buf, len); 62257429Smarkm} 623162852Sdes 62460573Skrisvoid 62560573Skrispacket_put_cstring(const char *str) 62660573Skris{ 627197679Sdes buffer_put_cstring(&active_state->outgoing_packet, str); 62860573Skris} 629162852Sdes 63060573Skrisvoid 63192555Sdespacket_put_raw(const void *buf, u_int len) 63260573Skris{ 633197679Sdes buffer_append(&active_state->outgoing_packet, buf, len); 63460573Skris} 635162852Sdes 63657429Smarkmvoid 63757429Smarkmpacket_put_bignum(BIGNUM * value) 63857429Smarkm{ 639197679Sdes buffer_put_bignum(&active_state->outgoing_packet, value); 64057429Smarkm} 641162852Sdes 64260573Skrisvoid 64360573Skrispacket_put_bignum2(BIGNUM * value) 64460573Skris{ 645197679Sdes buffer_put_bignum2(&active_state->outgoing_packet, value); 64660573Skris} 64757429Smarkm 648221420Sdes#ifdef OPENSSL_HAS_ECC 649221420Sdesvoid 650221420Sdespacket_put_ecpoint(const EC_GROUP *curve, const EC_POINT *point) 651221420Sdes{ 652221420Sdes buffer_put_ecpoint(&active_state->outgoing_packet, curve, point); 653221420Sdes} 654221420Sdes#endif 655221420Sdes 65657429Smarkm/* 65757429Smarkm * Finalizes and sends the packet. If the encryption key has been set, 65857429Smarkm * encrypts the packet before sending. 65957429Smarkm */ 66057429Smarkm 66192555Sdesstatic void 66276259Sgreenpacket_send1(void) 66357429Smarkm{ 66492555Sdes u_char buf[8], *cp; 66557429Smarkm int i, padding, len; 66676259Sgreen u_int checksum; 667137015Sdes u_int32_t rnd = 0; 66857429Smarkm 66957429Smarkm /* 67057429Smarkm * If using packet compression, compress the payload of the outgoing 67157429Smarkm * packet. 67257429Smarkm */ 673197679Sdes if (active_state->packet_compression) { 674197679Sdes buffer_clear(&active_state->compression_buffer); 67557429Smarkm /* Skip padding. */ 676197679Sdes buffer_consume(&active_state->outgoing_packet, 8); 67757429Smarkm /* padding */ 678197679Sdes buffer_append(&active_state->compression_buffer, 679197679Sdes "\0\0\0\0\0\0\0\0", 8); 680197679Sdes buffer_compress(&active_state->outgoing_packet, 681197679Sdes &active_state->compression_buffer); 682197679Sdes buffer_clear(&active_state->outgoing_packet); 683197679Sdes buffer_append(&active_state->outgoing_packet, 684197679Sdes buffer_ptr(&active_state->compression_buffer), 685197679Sdes buffer_len(&active_state->compression_buffer)); 68657429Smarkm } 68757429Smarkm /* Compute packet length without padding (add checksum, remove padding). */ 688197679Sdes len = buffer_len(&active_state->outgoing_packet) + 4 - 8; 68957429Smarkm 69060573Skris /* Insert padding. Initialized to zero in packet_start1() */ 69157429Smarkm padding = 8 - len % 8; 692197679Sdes if (!active_state->send_context.plaintext) { 693197679Sdes cp = buffer_ptr(&active_state->outgoing_packet); 69457429Smarkm for (i = 0; i < padding; i++) { 69557429Smarkm if (i % 4 == 0) 696137015Sdes rnd = arc4random(); 697137015Sdes cp[7 - i] = rnd & 0xff; 698137015Sdes rnd >>= 8; 69957429Smarkm } 70057429Smarkm } 701197679Sdes buffer_consume(&active_state->outgoing_packet, 8 - padding); 70257429Smarkm 70357429Smarkm /* Add check bytes. */ 704197679Sdes checksum = ssh_crc32(buffer_ptr(&active_state->outgoing_packet), 705197679Sdes buffer_len(&active_state->outgoing_packet)); 706162852Sdes put_u32(buf, checksum); 707197679Sdes buffer_append(&active_state->outgoing_packet, buf, 4); 70857429Smarkm 70957429Smarkm#ifdef PACKET_DEBUG 71057429Smarkm fprintf(stderr, "packet_send plain: "); 711197679Sdes buffer_dump(&active_state->outgoing_packet); 71257429Smarkm#endif 71357429Smarkm 71457429Smarkm /* Append to output. */ 715162852Sdes put_u32(buf, len); 716197679Sdes buffer_append(&active_state->output, buf, 4); 717197679Sdes cp = buffer_append_space(&active_state->output, 718197679Sdes buffer_len(&active_state->outgoing_packet)); 719262566Sdes if (cipher_crypt(&active_state->send_context, 0, cp, 720197679Sdes buffer_ptr(&active_state->outgoing_packet), 721262566Sdes buffer_len(&active_state->outgoing_packet), 0, 0) != 0) 722262566Sdes fatal("%s: cipher_crypt failed", __func__); 72357429Smarkm 72457429Smarkm#ifdef PACKET_DEBUG 72557429Smarkm fprintf(stderr, "encrypted: "); 726197679Sdes buffer_dump(&active_state->output); 72757429Smarkm#endif 728197679Sdes active_state->p_send.packets++; 729197679Sdes active_state->p_send.bytes += len + 730197679Sdes buffer_len(&active_state->outgoing_packet); 731197679Sdes buffer_clear(&active_state->outgoing_packet); 73257429Smarkm 73357429Smarkm /* 734157016Sdes * Note that the packet is now only buffered in output. It won't be 73557429Smarkm * actually sent until packet_write_wait or packet_write_poll is 73657429Smarkm * called. 73757429Smarkm */ 73857429Smarkm} 73957429Smarkm 74098675Sdesvoid 74176259Sgreenset_newkeys(int mode) 74276259Sgreen{ 74376259Sgreen Enc *enc; 74476259Sgreen Mac *mac; 74576259Sgreen Comp *comp; 74676259Sgreen CipherContext *cc; 747124208Sdes u_int64_t *max_blocks; 748137015Sdes int crypt_type; 74976259Sgreen 750113908Sdes debug2("set_newkeys: mode %d", mode); 75176259Sgreen 75292555Sdes if (mode == MODE_OUT) { 753197679Sdes cc = &active_state->send_context; 754137015Sdes crypt_type = CIPHER_ENCRYPT; 755197679Sdes active_state->p_send.packets = active_state->p_send.blocks = 0; 756197679Sdes max_blocks = &active_state->max_blocks_out; 75792555Sdes } else { 758197679Sdes cc = &active_state->receive_context; 759137015Sdes crypt_type = CIPHER_DECRYPT; 760197679Sdes active_state->p_read.packets = active_state->p_read.blocks = 0; 761197679Sdes max_blocks = &active_state->max_blocks_in; 76292555Sdes } 763197679Sdes if (active_state->newkeys[mode] != NULL) { 764113908Sdes debug("set_newkeys: rekeying"); 76592555Sdes cipher_cleanup(cc); 766197679Sdes enc = &active_state->newkeys[mode]->enc; 767197679Sdes mac = &active_state->newkeys[mode]->mac; 768197679Sdes comp = &active_state->newkeys[mode]->comp; 769181111Sdes mac_clear(mac); 770264377Sdes explicit_bzero(enc->iv, enc->iv_len); 771264377Sdes explicit_bzero(enc->key, enc->key_len); 772264377Sdes explicit_bzero(mac->key, mac->key_len); 773255767Sdes free(enc->name); 774255767Sdes free(enc->iv); 775255767Sdes free(enc->key); 776255767Sdes free(mac->name); 777255767Sdes free(mac->key); 778255767Sdes free(comp->name); 779255767Sdes free(active_state->newkeys[mode]); 78076259Sgreen } 781197679Sdes active_state->newkeys[mode] = kex_get_newkeys(mode); 782197679Sdes if (active_state->newkeys[mode] == NULL) 78376259Sgreen fatal("newkeys: no keys for mode %d", mode); 784197679Sdes enc = &active_state->newkeys[mode]->enc; 785197679Sdes mac = &active_state->newkeys[mode]->mac; 786197679Sdes comp = &active_state->newkeys[mode]->comp; 787248619Sdes if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0) 78876259Sgreen mac->enabled = 1; 78976259Sgreen DBG(debug("cipher_init_context: %d", mode)); 79092555Sdes cipher_init(cc, enc->cipher, enc->key, enc->key_len, 791248619Sdes enc->iv, enc->iv_len, crypt_type); 79298675Sdes /* Deleting the keys does not gain extra security */ 793264377Sdes /* explicit_bzero(enc->iv, enc->block_size); 794264377Sdes explicit_bzero(enc->key, enc->key_len); 795264377Sdes explicit_bzero(mac->key, mac->key_len); */ 796149749Sdes if ((comp->type == COMP_ZLIB || 797197679Sdes (comp->type == COMP_DELAYED && 798197679Sdes active_state->after_authentication)) && comp->enabled == 0) { 79976259Sgreen packet_init_compression(); 80076259Sgreen if (mode == MODE_OUT) 80176259Sgreen buffer_compress_init_send(6); 80276259Sgreen else 80376259Sgreen buffer_compress_init_recv(); 80476259Sgreen comp->enabled = 1; 80576259Sgreen } 806124208Sdes /* 807124208Sdes * The 2^(blocksize*2) limit is too expensive for 3DES, 808124208Sdes * blowfish, etc, so enforce a 1GB limit for small blocksizes. 809124208Sdes */ 810124208Sdes if (enc->block_size >= 16) 811124208Sdes *max_blocks = (u_int64_t)1 << (enc->block_size*2); 812124208Sdes else 813124208Sdes *max_blocks = ((u_int64_t)1 << 30) / enc->block_size; 814197679Sdes if (active_state->rekey_limit) 815197679Sdes *max_blocks = MIN(*max_blocks, 816197679Sdes active_state->rekey_limit / enc->block_size); 81776259Sgreen} 81876259Sgreen 81957429Smarkm/* 820149749Sdes * Delayed compression for SSH2 is enabled after authentication: 821162852Sdes * This happens on the server side after a SSH2_MSG_USERAUTH_SUCCESS is sent, 822149749Sdes * and on the client side after a SSH2_MSG_USERAUTH_SUCCESS is received. 823149749Sdes */ 824149749Sdesstatic void 825149749Sdespacket_enable_delayed_compress(void) 826149749Sdes{ 827149749Sdes Comp *comp = NULL; 828149749Sdes int mode; 829149749Sdes 830149749Sdes /* 831149749Sdes * Remember that we are past the authentication step, so rekeying 832149749Sdes * with COMP_DELAYED will turn on compression immediately. 833149749Sdes */ 834197679Sdes active_state->after_authentication = 1; 835149749Sdes for (mode = 0; mode < MODE_MAX; mode++) { 836162852Sdes /* protocol error: USERAUTH_SUCCESS received before NEWKEYS */ 837197679Sdes if (active_state->newkeys[mode] == NULL) 838162852Sdes continue; 839197679Sdes comp = &active_state->newkeys[mode]->comp; 840149749Sdes if (comp && !comp->enabled && comp->type == COMP_DELAYED) { 841149749Sdes packet_init_compression(); 842149749Sdes if (mode == MODE_OUT) 843149749Sdes buffer_compress_init_send(6); 844149749Sdes else 845149749Sdes buffer_compress_init_recv(); 846149749Sdes comp->enabled = 1; 847149749Sdes } 848149749Sdes } 849149749Sdes} 850149749Sdes 851149749Sdes/* 85260573Skris * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) 85360573Skris */ 85492555Sdesstatic void 855124208Sdespacket_send2_wrapped(void) 85660573Skris{ 85792555Sdes u_char type, *cp, *macbuf = NULL; 858248619Sdes u_char padlen, pad = 0; 859248619Sdes u_int i, len, authlen = 0, aadlen = 0; 860137015Sdes u_int32_t rnd = 0; 86160573Skris Enc *enc = NULL; 86260573Skris Mac *mac = NULL; 86360573Skris Comp *comp = NULL; 86460573Skris int block_size; 86560573Skris 866197679Sdes if (active_state->newkeys[MODE_OUT] != NULL) { 867197679Sdes enc = &active_state->newkeys[MODE_OUT]->enc; 868197679Sdes mac = &active_state->newkeys[MODE_OUT]->mac; 869197679Sdes comp = &active_state->newkeys[MODE_OUT]->comp; 870248619Sdes /* disable mac for authenticated encryption */ 871248619Sdes if ((authlen = cipher_authlen(enc->cipher)) != 0) 872248619Sdes mac = NULL; 87360573Skris } 87492555Sdes block_size = enc ? enc->block_size : 8; 875248619Sdes aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; 87660573Skris 877197679Sdes cp = buffer_ptr(&active_state->outgoing_packet); 87892555Sdes type = cp[5]; 87960573Skris 88060573Skris#ifdef PACKET_DEBUG 88160573Skris fprintf(stderr, "plain: "); 882197679Sdes buffer_dump(&active_state->outgoing_packet); 88360573Skris#endif 88460573Skris 88560573Skris if (comp && comp->enabled) { 886197679Sdes len = buffer_len(&active_state->outgoing_packet); 88760573Skris /* skip header, compress only payload */ 888197679Sdes buffer_consume(&active_state->outgoing_packet, 5); 889197679Sdes buffer_clear(&active_state->compression_buffer); 890197679Sdes buffer_compress(&active_state->outgoing_packet, 891197679Sdes &active_state->compression_buffer); 892197679Sdes buffer_clear(&active_state->outgoing_packet); 893197679Sdes buffer_append(&active_state->outgoing_packet, "\0\0\0\0\0", 5); 894197679Sdes buffer_append(&active_state->outgoing_packet, 895197679Sdes buffer_ptr(&active_state->compression_buffer), 896197679Sdes buffer_len(&active_state->compression_buffer)); 89760573Skris DBG(debug("compression: raw %d compressed %d", len, 898197679Sdes buffer_len(&active_state->outgoing_packet))); 89960573Skris } 90060573Skris 90160573Skris /* sizeof (packet_len + pad_len + payload) */ 902197679Sdes len = buffer_len(&active_state->outgoing_packet); 90360573Skris 90460573Skris /* 90560573Skris * calc size of padding, alloc space, get random data, 90660573Skris * minimum padding is 4 bytes 90760573Skris */ 908248619Sdes len -= aadlen; /* packet length is not encrypted for EtM modes */ 90960573Skris padlen = block_size - (len % block_size); 91060573Skris if (padlen < 4) 91160573Skris padlen += block_size; 912197679Sdes if (active_state->extra_pad) { 91392555Sdes /* will wrap if extra_pad+padlen > 255 */ 914197679Sdes active_state->extra_pad = 915197679Sdes roundup(active_state->extra_pad, block_size); 916197679Sdes pad = active_state->extra_pad - 917197679Sdes ((len + padlen) % active_state->extra_pad); 91898675Sdes debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 919197679Sdes pad, len, padlen, active_state->extra_pad); 92092555Sdes padlen += pad; 921197679Sdes active_state->extra_pad = 0; 92292555Sdes } 923197679Sdes cp = buffer_append_space(&active_state->outgoing_packet, padlen); 924197679Sdes if (enc && !active_state->send_context.plaintext) { 92560573Skris /* random padding */ 92660573Skris for (i = 0; i < padlen; i++) { 92760573Skris if (i % 4 == 0) 928137015Sdes rnd = arc4random(); 929137015Sdes cp[i] = rnd & 0xff; 930137015Sdes rnd >>= 8; 93160573Skris } 93260573Skris } else { 93360573Skris /* clear padding */ 934264377Sdes explicit_bzero(cp, padlen); 93560573Skris } 936248619Sdes /* sizeof (packet_len + pad_len + payload + padding) */ 937248619Sdes len = buffer_len(&active_state->outgoing_packet); 938248619Sdes cp = buffer_ptr(&active_state->outgoing_packet); 93960573Skris /* packet_length includes payload, padding and padding length field */ 940248619Sdes put_u32(cp, len - 4); 94192555Sdes cp[4] = padlen; 942248619Sdes DBG(debug("send: len %d (includes padlen %d, aadlen %d)", 943248619Sdes len, padlen, aadlen)); 94460573Skris 94560573Skris /* compute MAC over seqnr and packet(length fields, payload, padding) */ 946248619Sdes if (mac && mac->enabled && !mac->etm) { 947197679Sdes macbuf = mac_compute(mac, active_state->p_send.seqnr, 948248619Sdes buffer_ptr(&active_state->outgoing_packet), len); 949197679Sdes DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr)); 95060573Skris } 95160573Skris /* encrypt packet and append to output buffer. */ 952248619Sdes cp = buffer_append_space(&active_state->output, len + authlen); 953262566Sdes if (cipher_crypt(&active_state->send_context, active_state->p_send.seqnr, 954262566Sdes cp, buffer_ptr(&active_state->outgoing_packet), 955262566Sdes len - aadlen, aadlen, authlen) != 0) 956262566Sdes fatal("%s: cipher_crypt failed", __func__); 95760573Skris /* append unencrypted MAC */ 958248619Sdes if (mac && mac->enabled) { 959248619Sdes if (mac->etm) { 960248619Sdes /* EtM: compute mac over aadlen + cipher text */ 961248619Sdes macbuf = mac_compute(mac, 962248619Sdes active_state->p_send.seqnr, cp, len); 963248619Sdes DBG(debug("done calc MAC(EtM) out #%d", 964248619Sdes active_state->p_send.seqnr)); 965248619Sdes } 966197679Sdes buffer_append(&active_state->output, macbuf, mac->mac_len); 967248619Sdes } 96860573Skris#ifdef PACKET_DEBUG 96960573Skris fprintf(stderr, "encrypted: "); 970197679Sdes buffer_dump(&active_state->output); 97160573Skris#endif 97260573Skris /* increment sequence number for outgoing packets */ 973197679Sdes if (++active_state->p_send.seqnr == 0) 974124208Sdes logit("outgoing seqnr wraps around"); 975197679Sdes if (++active_state->p_send.packets == 0) 976124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 977124208Sdes fatal("XXX too many packets with same key"); 978248619Sdes active_state->p_send.blocks += len / block_size; 979248619Sdes active_state->p_send.bytes += len; 980197679Sdes buffer_clear(&active_state->outgoing_packet); 98160573Skris 98276259Sgreen if (type == SSH2_MSG_NEWKEYS) 98376259Sgreen set_newkeys(MODE_OUT); 984197679Sdes else if (type == SSH2_MSG_USERAUTH_SUCCESS && active_state->server_side) 985149749Sdes packet_enable_delayed_compress(); 98660573Skris} 98760573Skris 988124208Sdesstatic void 989124208Sdespacket_send2(void) 990124208Sdes{ 991124208Sdes struct packet *p; 992124208Sdes u_char type, *cp; 993124208Sdes 994197679Sdes cp = buffer_ptr(&active_state->outgoing_packet); 995124208Sdes type = cp[5]; 996124208Sdes 997124208Sdes /* during rekeying we can only send key exchange messages */ 998197679Sdes if (active_state->rekeying) { 999240075Sdes if ((type < SSH2_MSG_TRANSPORT_MIN) || 1000240075Sdes (type > SSH2_MSG_TRANSPORT_MAX) || 1001240075Sdes (type == SSH2_MSG_SERVICE_REQUEST) || 1002240075Sdes (type == SSH2_MSG_SERVICE_ACCEPT)) { 1003124208Sdes debug("enqueue packet: %u", type); 1004258343Sdes p = xcalloc(1, sizeof(*p)); 1005124208Sdes p->type = type; 1006197679Sdes memcpy(&p->payload, &active_state->outgoing_packet, 1007197679Sdes sizeof(Buffer)); 1008197679Sdes buffer_init(&active_state->outgoing_packet); 1009197679Sdes TAILQ_INSERT_TAIL(&active_state->outgoing, p, next); 1010124208Sdes return; 1011124208Sdes } 1012124208Sdes } 1013124208Sdes 1014124208Sdes /* rekeying starts with sending KEXINIT */ 1015124208Sdes if (type == SSH2_MSG_KEXINIT) 1016197679Sdes active_state->rekeying = 1; 1017124208Sdes 1018124208Sdes packet_send2_wrapped(); 1019124208Sdes 1020124208Sdes /* after a NEWKEYS message we can send the complete queue */ 1021124208Sdes if (type == SSH2_MSG_NEWKEYS) { 1022197679Sdes active_state->rekeying = 0; 1023255767Sdes active_state->rekey_time = monotime(); 1024197679Sdes while ((p = TAILQ_FIRST(&active_state->outgoing))) { 1025124208Sdes type = p->type; 1026124208Sdes debug("dequeue packet: %u", type); 1027197679Sdes buffer_free(&active_state->outgoing_packet); 1028197679Sdes memcpy(&active_state->outgoing_packet, &p->payload, 1029124208Sdes sizeof(Buffer)); 1030197679Sdes TAILQ_REMOVE(&active_state->outgoing, p, next); 1031255767Sdes free(p); 1032124208Sdes packet_send2_wrapped(); 1033124208Sdes } 1034124208Sdes } 1035124208Sdes} 1036124208Sdes 103760573Skrisvoid 103892555Sdespacket_send(void) 103960573Skris{ 104092555Sdes if (compat20) 104160573Skris packet_send2(); 104260573Skris else 104360573Skris packet_send1(); 104460573Skris DBG(debug("packet_send done")); 104560573Skris} 104660573Skris 104760573Skris/* 104857429Smarkm * Waits until a packet has been received, and returns its type. Note that 104957429Smarkm * no other data is processed until this returns, so this function should not 105057429Smarkm * be used during the interactive session. 105157429Smarkm */ 105257429Smarkm 105357429Smarkmint 105492555Sdespacket_read_seqnr(u_int32_t *seqnr_p) 105557429Smarkm{ 1056255767Sdes int type, len, ret, cont, ms_remain = 0; 105776259Sgreen fd_set *setp; 105857429Smarkm char buf[8192]; 1059181111Sdes struct timeval timeout, start, *timeoutp = NULL; 1060181111Sdes 106160573Skris DBG(debug("packet_read()")); 106257429Smarkm 1063197679Sdes setp = (fd_set *)xcalloc(howmany(active_state->connection_in + 1, 1064197679Sdes NFDBITS), sizeof(fd_mask)); 106576259Sgreen 106657429Smarkm /* Since we are blocking, ensure that all written packets have been sent. */ 106757429Smarkm packet_write_wait(); 106857429Smarkm 106957429Smarkm /* Stay in the loop until we have received a complete packet. */ 107057429Smarkm for (;;) { 107157429Smarkm /* Try to read a packet from the buffer. */ 107292555Sdes type = packet_read_poll_seqnr(seqnr_p); 107392555Sdes if (!compat20 && ( 107460573Skris type == SSH_SMSG_SUCCESS 107557429Smarkm || type == SSH_SMSG_FAILURE 107657429Smarkm || type == SSH_CMSG_EOF 107760573Skris || type == SSH_CMSG_EXIT_CONFIRMATION)) 107892555Sdes packet_check_eom(); 107957429Smarkm /* If we got a packet, return it. */ 108076259Sgreen if (type != SSH_MSG_NONE) { 1081255767Sdes free(setp); 108257429Smarkm return type; 108376259Sgreen } 108457429Smarkm /* 108557429Smarkm * Otherwise, wait for some data to arrive, add it to the 108657429Smarkm * buffer, and try again. 108757429Smarkm */ 1088197679Sdes memset(setp, 0, howmany(active_state->connection_in + 1, 1089197679Sdes NFDBITS) * sizeof(fd_mask)); 1090197679Sdes FD_SET(active_state->connection_in, setp); 109157429Smarkm 1092197679Sdes if (active_state->packet_timeout_ms > 0) { 1093197679Sdes ms_remain = active_state->packet_timeout_ms; 1094181111Sdes timeoutp = &timeout; 1095181111Sdes } 109657429Smarkm /* Wait for some data to arrive. */ 1097181111Sdes for (;;) { 1098197679Sdes if (active_state->packet_timeout_ms != -1) { 1099181111Sdes ms_to_timeval(&timeout, ms_remain); 1100181111Sdes gettimeofday(&start, NULL); 1101181111Sdes } 1102197679Sdes if ((ret = select(active_state->connection_in + 1, setp, 1103197679Sdes NULL, NULL, timeoutp)) >= 0) 1104181111Sdes break; 1105197679Sdes if (errno != EAGAIN && errno != EINTR && 1106181111Sdes errno != EWOULDBLOCK) 1107181111Sdes break; 1108197679Sdes if (active_state->packet_timeout_ms == -1) 1109181111Sdes continue; 1110181111Sdes ms_subtract_diff(&start, &ms_remain); 1111181111Sdes if (ms_remain <= 0) { 1112181111Sdes ret = 0; 1113181111Sdes break; 1114181111Sdes } 1115181111Sdes } 1116181111Sdes if (ret == 0) { 1117181111Sdes logit("Connection to %.200s timed out while " 1118181111Sdes "waiting to read", get_remote_ipaddr()); 1119181111Sdes cleanup_exit(255); 1120181111Sdes } 112157429Smarkm /* Read data from the socket. */ 1122197679Sdes do { 1123197679Sdes cont = 0; 1124197679Sdes len = roaming_read(active_state->connection_in, buf, 1125197679Sdes sizeof(buf), &cont); 1126197679Sdes } while (len == 0 && cont); 112757429Smarkm if (len == 0) { 1128124208Sdes logit("Connection closed by %.200s", get_remote_ipaddr()); 1129126274Sdes cleanup_exit(255); 113057429Smarkm } 113157429Smarkm if (len < 0) 113257429Smarkm fatal("Read from socket failed: %.100s", strerror(errno)); 113357429Smarkm /* Append it to the buffer. */ 113457429Smarkm packet_process_incoming(buf, len); 113557429Smarkm } 113657429Smarkm /* NOTREACHED */ 113757429Smarkm} 113857429Smarkm 113992555Sdesint 114092555Sdespacket_read(void) 114192555Sdes{ 114292555Sdes return packet_read_seqnr(NULL); 114392555Sdes} 114492555Sdes 114557429Smarkm/* 114657429Smarkm * Waits until a packet has been received, verifies that its type matches 114757429Smarkm * that given, and gives a fatal error and exits if there is a mismatch. 114857429Smarkm */ 114957429Smarkm 115057429Smarkmvoid 115192555Sdespacket_read_expect(int expected_type) 115257429Smarkm{ 115357429Smarkm int type; 115457429Smarkm 115592555Sdes type = packet_read(); 115657429Smarkm if (type != expected_type) 115757429Smarkm packet_disconnect("Protocol error: expected packet type %d, got %d", 115860573Skris expected_type, type); 115957429Smarkm} 116057429Smarkm 116157429Smarkm/* Checks if a full packet is available in the data received so far via 116257429Smarkm * packet_process_incoming. If so, reads the packet; otherwise returns 116357429Smarkm * SSH_MSG_NONE. This does not wait for data from the connection. 116457429Smarkm * 116557429Smarkm * SSH_MSG_DISCONNECT is handled specially here. Also, 116657429Smarkm * SSH_MSG_IGNORE messages are skipped by this function and are never returned 116757429Smarkm * to higher levels. 116857429Smarkm */ 116957429Smarkm 117092555Sdesstatic int 117192555Sdespacket_read_poll1(void) 117257429Smarkm{ 117376259Sgreen u_int len, padded_len; 117492555Sdes u_char *cp, type; 117576259Sgreen u_int checksum, stored_checksum; 117657429Smarkm 117757429Smarkm /* Check if input size is less than minimum packet size. */ 1178197679Sdes if (buffer_len(&active_state->input) < 4 + 8) 117957429Smarkm return SSH_MSG_NONE; 118057429Smarkm /* Get length of incoming packet. */ 1181197679Sdes cp = buffer_ptr(&active_state->input); 1182162852Sdes len = get_u32(cp); 118357429Smarkm if (len < 1 + 2 + 2 || len > 256 * 1024) 1184113908Sdes packet_disconnect("Bad packet length %u.", len); 118557429Smarkm padded_len = (len + 8) & ~7; 118657429Smarkm 118757429Smarkm /* Check if the packet has been entirely received. */ 1188197679Sdes if (buffer_len(&active_state->input) < 4 + padded_len) 118957429Smarkm return SSH_MSG_NONE; 119057429Smarkm 119157429Smarkm /* The entire packet is in buffer. */ 119257429Smarkm 119357429Smarkm /* Consume packet length. */ 1194197679Sdes buffer_consume(&active_state->input, 4); 119557429Smarkm 119692555Sdes /* 119792555Sdes * Cryptographic attack detector for ssh 119892555Sdes * (C)1998 CORE-SDI, Buenos Aires Argentina 119992555Sdes * Ariel Futoransky(futo@core-sdi.com) 120092555Sdes */ 1201197679Sdes if (!active_state->receive_context.plaintext) { 1202197679Sdes switch (detect_attack(buffer_ptr(&active_state->input), 1203197679Sdes padded_len)) { 1204162852Sdes case DEATTACK_DETECTED: 1205162852Sdes packet_disconnect("crc32 compensation attack: " 1206162852Sdes "network attack detected"); 1207162852Sdes case DEATTACK_DOS_DETECTED: 1208162852Sdes packet_disconnect("deattack denial of " 1209162852Sdes "service detected"); 1210162852Sdes } 1211162852Sdes } 121292555Sdes 121392555Sdes /* Decrypt data to incoming_packet. */ 1214197679Sdes buffer_clear(&active_state->incoming_packet); 1215197679Sdes cp = buffer_append_space(&active_state->incoming_packet, padded_len); 1216262566Sdes if (cipher_crypt(&active_state->receive_context, 0, cp, 1217262566Sdes buffer_ptr(&active_state->input), padded_len, 0, 0) != 0) 1218262566Sdes fatal("%s: cipher_crypt failed", __func__); 121992555Sdes 1220197679Sdes buffer_consume(&active_state->input, padded_len); 122157429Smarkm 122257429Smarkm#ifdef PACKET_DEBUG 122357429Smarkm fprintf(stderr, "read_poll plain: "); 1224197679Sdes buffer_dump(&active_state->incoming_packet); 122557429Smarkm#endif 122657429Smarkm 122757429Smarkm /* Compute packet checksum. */ 1228197679Sdes checksum = ssh_crc32(buffer_ptr(&active_state->incoming_packet), 1229197679Sdes buffer_len(&active_state->incoming_packet) - 4); 123057429Smarkm 123157429Smarkm /* Skip padding. */ 1232197679Sdes buffer_consume(&active_state->incoming_packet, 8 - len % 8); 123357429Smarkm 123457429Smarkm /* Test check bytes. */ 1235197679Sdes if (len != buffer_len(&active_state->incoming_packet)) 123692555Sdes packet_disconnect("packet_read_poll1: len %d != buffer_len %d.", 1237197679Sdes len, buffer_len(&active_state->incoming_packet)); 123857429Smarkm 1239197679Sdes cp = (u_char *)buffer_ptr(&active_state->incoming_packet) + len - 4; 1240162852Sdes stored_checksum = get_u32(cp); 124157429Smarkm if (checksum != stored_checksum) 124257429Smarkm packet_disconnect("Corrupted check bytes on input."); 1243197679Sdes buffer_consume_end(&active_state->incoming_packet, 4); 124457429Smarkm 1245197679Sdes if (active_state->packet_compression) { 1246197679Sdes buffer_clear(&active_state->compression_buffer); 1247197679Sdes buffer_uncompress(&active_state->incoming_packet, 1248197679Sdes &active_state->compression_buffer); 1249197679Sdes buffer_clear(&active_state->incoming_packet); 1250197679Sdes buffer_append(&active_state->incoming_packet, 1251197679Sdes buffer_ptr(&active_state->compression_buffer), 1252197679Sdes buffer_len(&active_state->compression_buffer)); 125357429Smarkm } 1254197679Sdes active_state->p_read.packets++; 1255197679Sdes active_state->p_read.bytes += padded_len + 4; 1256197679Sdes type = buffer_get_char(&active_state->incoming_packet); 1257146998Sdes if (type < SSH_MSG_MIN || type > SSH_MSG_MAX) 1258146998Sdes packet_disconnect("Invalid ssh1 packet type: %d", type); 125992555Sdes return type; 126060573Skris} 126157429Smarkm 126292555Sdesstatic int 126392555Sdespacket_read_poll2(u_int32_t *seqnr_p) 126460573Skris{ 126576259Sgreen u_int padlen, need; 1266248619Sdes u_char *macbuf = NULL, *cp, type; 1267248619Sdes u_int maclen, authlen = 0, aadlen = 0, block_size; 126860573Skris Enc *enc = NULL; 126960573Skris Mac *mac = NULL; 127060573Skris Comp *comp = NULL; 127157429Smarkm 1272197679Sdes if (active_state->packet_discard) 1273192595Sdes return SSH_MSG_NONE; 1274192595Sdes 1275197679Sdes if (active_state->newkeys[MODE_IN] != NULL) { 1276197679Sdes enc = &active_state->newkeys[MODE_IN]->enc; 1277197679Sdes mac = &active_state->newkeys[MODE_IN]->mac; 1278197679Sdes comp = &active_state->newkeys[MODE_IN]->comp; 1279248619Sdes /* disable mac for authenticated encryption */ 1280248619Sdes if ((authlen = cipher_authlen(enc->cipher)) != 0) 1281248619Sdes mac = NULL; 128257429Smarkm } 128360573Skris maclen = mac && mac->enabled ? mac->mac_len : 0; 128492555Sdes block_size = enc ? enc->block_size : 8; 1285248619Sdes aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0; 128660573Skris 1287248619Sdes if (aadlen && active_state->packlen == 0) { 1288262566Sdes if (cipher_get_length(&active_state->receive_context, 1289262566Sdes &active_state->packlen, 1290262566Sdes active_state->p_read.seqnr, 1291262566Sdes buffer_ptr(&active_state->input), 1292262566Sdes buffer_len(&active_state->input)) != 0) 1293248619Sdes return SSH_MSG_NONE; 1294248619Sdes if (active_state->packlen < 1 + 4 || 1295248619Sdes active_state->packlen > PACKET_MAX_SIZE) { 1296248619Sdes#ifdef PACKET_DEBUG 1297248619Sdes buffer_dump(&active_state->input); 1298248619Sdes#endif 1299248619Sdes logit("Bad packet length %u.", active_state->packlen); 1300248619Sdes packet_disconnect("Packet corrupt"); 1301248619Sdes } 1302248619Sdes buffer_clear(&active_state->incoming_packet); 1303248619Sdes } else if (active_state->packlen == 0) { 130460573Skris /* 130560573Skris * check if input size is less than the cipher block size, 130660573Skris * decrypt first block and extract length of incoming packet 130760573Skris */ 1308197679Sdes if (buffer_len(&active_state->input) < block_size) 130960573Skris return SSH_MSG_NONE; 1310197679Sdes buffer_clear(&active_state->incoming_packet); 1311197679Sdes cp = buffer_append_space(&active_state->incoming_packet, 131260573Skris block_size); 1313262566Sdes if (cipher_crypt(&active_state->receive_context, 1314262566Sdes active_state->p_read.seqnr, cp, 1315262566Sdes buffer_ptr(&active_state->input), block_size, 0, 0) != 0) 1316262566Sdes fatal("Decryption integrity check failed"); 1317197679Sdes cp = buffer_ptr(&active_state->incoming_packet); 1318240075Sdes 1319197679Sdes active_state->packlen = get_u32(cp); 1320197679Sdes if (active_state->packlen < 1 + 4 || 1321197679Sdes active_state->packlen > PACKET_MAX_SIZE) { 1322124208Sdes#ifdef PACKET_DEBUG 1323197679Sdes buffer_dump(&active_state->incoming_packet); 1324124208Sdes#endif 1325197679Sdes logit("Bad packet length %u.", active_state->packlen); 1326197679Sdes packet_start_discard(enc, mac, active_state->packlen, 1327192595Sdes PACKET_MAX_SIZE); 1328192595Sdes return SSH_MSG_NONE; 132960573Skris } 1330197679Sdes buffer_consume(&active_state->input, block_size); 133160573Skris } 1332248619Sdes DBG(debug("input: packet len %u", active_state->packlen+4)); 1333248619Sdes if (aadlen) { 1334248619Sdes /* only the payload is encrypted */ 1335248619Sdes need = active_state->packlen; 1336248619Sdes } else { 1337248619Sdes /* 1338248619Sdes * the payload size and the payload are encrypted, but we 1339248619Sdes * have a partial packet of block_size bytes 1340248619Sdes */ 1341248619Sdes need = 4 + active_state->packlen - block_size; 1342248619Sdes } 1343248619Sdes DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d," 1344248619Sdes " aadlen %d", block_size, need, maclen, authlen, aadlen)); 1345192595Sdes if (need % block_size != 0) { 1346192595Sdes logit("padding error: need %d block %d mod %d", 134760573Skris need, block_size, need % block_size); 1348197679Sdes packet_start_discard(enc, mac, active_state->packlen, 1349192595Sdes PACKET_MAX_SIZE - block_size); 1350192595Sdes return SSH_MSG_NONE; 1351192595Sdes } 135260573Skris /* 135360573Skris * check if the entire packet has been received and 1354248619Sdes * decrypt into incoming_packet: 1355248619Sdes * 'aadlen' bytes are unencrypted, but authenticated. 1356248619Sdes * 'need' bytes are encrypted, followed by either 1357248619Sdes * 'authlen' bytes of authentication tag or 1358248619Sdes * 'maclen' bytes of message authentication code. 135960573Skris */ 1360248619Sdes if (buffer_len(&active_state->input) < aadlen + need + authlen + maclen) 136160573Skris return SSH_MSG_NONE; 136260573Skris#ifdef PACKET_DEBUG 136360573Skris fprintf(stderr, "read_poll enc/full: "); 1364197679Sdes buffer_dump(&active_state->input); 136560573Skris#endif 1366248619Sdes /* EtM: compute mac over encrypted input */ 1367248619Sdes if (mac && mac->enabled && mac->etm) 1368248619Sdes macbuf = mac_compute(mac, active_state->p_read.seqnr, 1369248619Sdes buffer_ptr(&active_state->input), aadlen + need); 1370248619Sdes cp = buffer_append_space(&active_state->incoming_packet, aadlen + need); 1371262566Sdes if (cipher_crypt(&active_state->receive_context, 1372262566Sdes active_state->p_read.seqnr, cp, 1373262566Sdes buffer_ptr(&active_state->input), need, aadlen, authlen) != 0) 1374262566Sdes fatal("Decryption integrity check failed"); 1375248619Sdes buffer_consume(&active_state->input, aadlen + need + authlen); 137660573Skris /* 137760573Skris * compute MAC over seqnr and packet, 137860573Skris * increment sequence number for incoming packet 137960573Skris */ 138060573Skris if (mac && mac->enabled) { 1381248619Sdes if (!mac->etm) 1382248619Sdes macbuf = mac_compute(mac, active_state->p_read.seqnr, 1383248619Sdes buffer_ptr(&active_state->incoming_packet), 1384248619Sdes buffer_len(&active_state->incoming_packet)); 1385215116Sdes if (timingsafe_bcmp(macbuf, buffer_ptr(&active_state->input), 1386197679Sdes mac->mac_len) != 0) { 1387192595Sdes logit("Corrupted MAC on input."); 1388192595Sdes if (need > PACKET_MAX_SIZE) 1389192595Sdes fatal("internal error need %d", need); 1390197679Sdes packet_start_discard(enc, mac, active_state->packlen, 1391192595Sdes PACKET_MAX_SIZE - need); 1392192595Sdes return SSH_MSG_NONE; 1393192595Sdes } 1394192595Sdes 1395197679Sdes DBG(debug("MAC #%d ok", active_state->p_read.seqnr)); 1396197679Sdes buffer_consume(&active_state->input, mac->mac_len); 139760573Skris } 1398192595Sdes /* XXX now it's safe to use fatal/packet_disconnect */ 139992555Sdes if (seqnr_p != NULL) 1400197679Sdes *seqnr_p = active_state->p_read.seqnr; 1401197679Sdes if (++active_state->p_read.seqnr == 0) 1402124208Sdes logit("incoming seqnr wraps around"); 1403197679Sdes if (++active_state->p_read.packets == 0) 1404124208Sdes if (!(datafellows & SSH_BUG_NOREKEY)) 1405124208Sdes fatal("XXX too many packets with same key"); 1406197679Sdes active_state->p_read.blocks += (active_state->packlen + 4) / block_size; 1407197679Sdes active_state->p_read.bytes += active_state->packlen + 4; 140860573Skris 140960573Skris /* get padlen */ 1410197679Sdes cp = buffer_ptr(&active_state->incoming_packet); 141192555Sdes padlen = cp[4]; 141260573Skris DBG(debug("input: padlen %d", padlen)); 141360573Skris if (padlen < 4) 141460573Skris packet_disconnect("Corrupted padlen %d on input.", padlen); 141560573Skris 141660573Skris /* skip packet size + padlen, discard padding */ 1417197679Sdes buffer_consume(&active_state->incoming_packet, 4 + 1); 1418197679Sdes buffer_consume_end(&active_state->incoming_packet, padlen); 141960573Skris 1420197679Sdes DBG(debug("input: len before de-compress %d", 1421197679Sdes buffer_len(&active_state->incoming_packet))); 142260573Skris if (comp && comp->enabled) { 1423197679Sdes buffer_clear(&active_state->compression_buffer); 1424197679Sdes buffer_uncompress(&active_state->incoming_packet, 1425197679Sdes &active_state->compression_buffer); 1426197679Sdes buffer_clear(&active_state->incoming_packet); 1427197679Sdes buffer_append(&active_state->incoming_packet, 1428197679Sdes buffer_ptr(&active_state->compression_buffer), 1429197679Sdes buffer_len(&active_state->compression_buffer)); 1430106121Sdes DBG(debug("input: len after de-compress %d", 1431197679Sdes buffer_len(&active_state->incoming_packet))); 143260573Skris } 143360573Skris /* 143460573Skris * get packet type, implies consume. 143560573Skris * return length of payload (without type field) 143660573Skris */ 1437197679Sdes type = buffer_get_char(&active_state->incoming_packet); 1438146998Sdes if (type < SSH2_MSG_MIN || type >= SSH2_MSG_LOCAL_MIN) 1439146998Sdes packet_disconnect("Invalid ssh2 packet type: %d", type); 144076259Sgreen if (type == SSH2_MSG_NEWKEYS) 144176259Sgreen set_newkeys(MODE_IN); 1442197679Sdes else if (type == SSH2_MSG_USERAUTH_SUCCESS && 1443197679Sdes !active_state->server_side) 1444149749Sdes packet_enable_delayed_compress(); 144560573Skris#ifdef PACKET_DEBUG 144676259Sgreen fprintf(stderr, "read/plain[%d]:\r\n", type); 1447197679Sdes buffer_dump(&active_state->incoming_packet); 144860573Skris#endif 144992555Sdes /* reset for next packet */ 1450197679Sdes active_state->packlen = 0; 145192555Sdes return type; 145257429Smarkm} 145357429Smarkm 145460573Skrisint 145592555Sdespacket_read_poll_seqnr(u_int32_t *seqnr_p) 145660573Skris{ 145799060Sdes u_int reason, seqnr; 145892555Sdes u_char type; 145960573Skris char *msg; 146092555Sdes 146160573Skris for (;;) { 146292555Sdes if (compat20) { 146392555Sdes type = packet_read_poll2(seqnr_p); 1464181111Sdes if (type) { 1465197679Sdes active_state->keep_alive_timeouts = 0; 146660573Skris DBG(debug("received packet type %d", type)); 1467181111Sdes } 146892555Sdes switch (type) { 146960573Skris case SSH2_MSG_IGNORE: 1470181111Sdes debug3("Received SSH2_MSG_IGNORE"); 147160573Skris break; 147260573Skris case SSH2_MSG_DEBUG: 147360573Skris packet_get_char(); 147460573Skris msg = packet_get_string(NULL); 147560573Skris debug("Remote: %.900s", msg); 1476255767Sdes free(msg); 147760573Skris msg = packet_get_string(NULL); 1478255767Sdes free(msg); 147960573Skris break; 148060573Skris case SSH2_MSG_DISCONNECT: 148160573Skris reason = packet_get_int(); 148260573Skris msg = packet_get_string(NULL); 1483249475Sdes /* Ignore normal client exit notifications */ 1484249475Sdes do_log2(active_state->server_side && 1485249475Sdes reason == SSH2_DISCONNECT_BY_APPLICATION ? 1486250739Sdes SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR, 1487249475Sdes "Received disconnect from %s: %u: %.400s", 148899060Sdes get_remote_ipaddr(), reason, msg); 1489255767Sdes free(msg); 1490126274Sdes cleanup_exit(255); 149160573Skris break; 149292555Sdes case SSH2_MSG_UNIMPLEMENTED: 149392555Sdes seqnr = packet_get_int(); 149499060Sdes debug("Received SSH2_MSG_UNIMPLEMENTED for %u", 149599060Sdes seqnr); 149692555Sdes break; 149760573Skris default: 149860573Skris return type; 149976259Sgreen } 150060573Skris } else { 150192555Sdes type = packet_read_poll1(); 150292555Sdes switch (type) { 1503255767Sdes case SSH_MSG_NONE: 1504255767Sdes return SSH_MSG_NONE; 150560573Skris case SSH_MSG_IGNORE: 150660573Skris break; 150760573Skris case SSH_MSG_DEBUG: 150860573Skris msg = packet_get_string(NULL); 150960573Skris debug("Remote: %.900s", msg); 1510255767Sdes free(msg); 151160573Skris break; 151260573Skris case SSH_MSG_DISCONNECT: 151360573Skris msg = packet_get_string(NULL); 1514249475Sdes logit("Received disconnect from %s: %.400s", 151599060Sdes get_remote_ipaddr(), msg); 1516126274Sdes cleanup_exit(255); 151760573Skris break; 151860573Skris default: 1519255767Sdes DBG(debug("received packet type %d", type)); 152060573Skris return type; 152176259Sgreen } 152260573Skris } 152360573Skris } 152460573Skris} 152560573Skris 152657429Smarkm/* 152757429Smarkm * Buffers the given amount of input characters. This is intended to be used 152857429Smarkm * together with packet_read_poll. 152957429Smarkm */ 153057429Smarkm 153157429Smarkmvoid 153276259Sgreenpacket_process_incoming(const char *buf, u_int len) 153357429Smarkm{ 1534197679Sdes if (active_state->packet_discard) { 1535197679Sdes active_state->keep_alive_timeouts = 0; /* ?? */ 1536197679Sdes if (len >= active_state->packet_discard) 1537192595Sdes packet_stop_discard(); 1538197679Sdes active_state->packet_discard -= len; 1539192595Sdes return; 1540192595Sdes } 1541197679Sdes buffer_append(&active_state->input, buf, len); 154257429Smarkm} 154357429Smarkm 154457429Smarkm/* Returns a character from the packet. */ 154557429Smarkm 154676259Sgreenu_int 154792555Sdespacket_get_char(void) 154857429Smarkm{ 154957429Smarkm char ch; 1550106121Sdes 1551197679Sdes buffer_get(&active_state->incoming_packet, &ch, 1); 155276259Sgreen return (u_char) ch; 155357429Smarkm} 155457429Smarkm 155557429Smarkm/* Returns an integer from the packet data. */ 155657429Smarkm 155776259Sgreenu_int 155892555Sdespacket_get_int(void) 155957429Smarkm{ 1560197679Sdes return buffer_get_int(&active_state->incoming_packet); 156157429Smarkm} 156257429Smarkm 1563197679Sdes/* Returns an 64 bit integer from the packet data. */ 1564197679Sdes 1565197679Sdesu_int64_t 1566197679Sdespacket_get_int64(void) 1567197679Sdes{ 1568197679Sdes return buffer_get_int64(&active_state->incoming_packet); 1569197679Sdes} 1570197679Sdes 157157429Smarkm/* 157257429Smarkm * Returns an arbitrary precision integer from the packet data. The integer 157357429Smarkm * must have been initialized before this call. 157457429Smarkm */ 157557429Smarkm 157657429Smarkmvoid 157792555Sdespacket_get_bignum(BIGNUM * value) 157857429Smarkm{ 1579197679Sdes buffer_get_bignum(&active_state->incoming_packet, value); 158057429Smarkm} 158157429Smarkm 158260573Skrisvoid 158392555Sdespacket_get_bignum2(BIGNUM * value) 158460573Skris{ 1585197679Sdes buffer_get_bignum2(&active_state->incoming_packet, value); 158660573Skris} 158760573Skris 1588221420Sdes#ifdef OPENSSL_HAS_ECC 1589221420Sdesvoid 1590221420Sdespacket_get_ecpoint(const EC_GROUP *curve, EC_POINT *point) 1591221420Sdes{ 1592221420Sdes buffer_get_ecpoint(&active_state->incoming_packet, curve, point); 1593221420Sdes} 1594221420Sdes#endif 1595221420Sdes 159692555Sdesvoid * 1597149749Sdespacket_get_raw(u_int *length_ptr) 159860573Skris{ 1599197679Sdes u_int bytes = buffer_len(&active_state->incoming_packet); 1600106121Sdes 160160573Skris if (length_ptr != NULL) 160260573Skris *length_ptr = bytes; 1603197679Sdes return buffer_ptr(&active_state->incoming_packet); 160460573Skris} 160560573Skris 160660573Skrisint 160760573Skrispacket_remaining(void) 160860573Skris{ 1609197679Sdes return buffer_len(&active_state->incoming_packet); 161060573Skris} 161160573Skris 161257429Smarkm/* 161357429Smarkm * Returns a string from the packet data. The string is allocated using 161457429Smarkm * xmalloc; it is the responsibility of the calling program to free it when 161557429Smarkm * no longer needed. The length_ptr argument may be NULL, or point to an 161657429Smarkm * integer into which the length of the string is stored. 161757429Smarkm */ 161857429Smarkm 161992555Sdesvoid * 162076259Sgreenpacket_get_string(u_int *length_ptr) 162157429Smarkm{ 1622197679Sdes return buffer_get_string(&active_state->incoming_packet, length_ptr); 162357429Smarkm} 162457429Smarkm 1625181111Sdesvoid * 1626181111Sdespacket_get_string_ptr(u_int *length_ptr) 1627181111Sdes{ 1628197679Sdes return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr); 1629181111Sdes} 1630181111Sdes 1631221420Sdes/* Ensures the returned string has no embedded \0 characters in it. */ 1632221420Sdeschar * 1633221420Sdespacket_get_cstring(u_int *length_ptr) 1634221420Sdes{ 1635221420Sdes return buffer_get_cstring(&active_state->incoming_packet, length_ptr); 1636221420Sdes} 1637221420Sdes 163857429Smarkm/* 163957429Smarkm * Sends a diagnostic message from the server to the client. This message 164057429Smarkm * can be sent at any time (but not while constructing another message). The 164157429Smarkm * message is printed immediately, but only if the client is being executed 164257429Smarkm * in verbose mode. These messages are primarily intended to ease debugging 164357429Smarkm * authentication problems. The length of the formatted message must not 164457429Smarkm * exceed 1024 bytes. This will automatically call packet_write_wait. 164557429Smarkm */ 164657429Smarkm 164757429Smarkmvoid 164857429Smarkmpacket_send_debug(const char *fmt,...) 164957429Smarkm{ 165057429Smarkm char buf[1024]; 165157429Smarkm va_list args; 165257429Smarkm 165376259Sgreen if (compat20 && (datafellows & SSH_BUG_DEBUG)) 165476259Sgreen return; 165576259Sgreen 165657429Smarkm va_start(args, fmt); 165757429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 165857429Smarkm va_end(args); 165957429Smarkm 166060573Skris if (compat20) { 166160573Skris packet_start(SSH2_MSG_DEBUG); 166260573Skris packet_put_char(0); /* bool: always display */ 166360573Skris packet_put_cstring(buf); 166460573Skris packet_put_cstring(""); 166560573Skris } else { 166660573Skris packet_start(SSH_MSG_DEBUG); 166760573Skris packet_put_cstring(buf); 166860573Skris } 166957429Smarkm packet_send(); 167057429Smarkm packet_write_wait(); 167157429Smarkm} 167257429Smarkm 167357429Smarkm/* 167457429Smarkm * Logs the error plus constructs and sends a disconnect packet, closes the 167557429Smarkm * connection, and exits. This function never returns. The error message 167657429Smarkm * should not contain a newline. The length of the formatted message must 167757429Smarkm * not exceed 1024 bytes. 167857429Smarkm */ 167957429Smarkm 168057429Smarkmvoid 168157429Smarkmpacket_disconnect(const char *fmt,...) 168257429Smarkm{ 168357429Smarkm char buf[1024]; 168457429Smarkm va_list args; 168557429Smarkm static int disconnecting = 0; 1686106121Sdes 168757429Smarkm if (disconnecting) /* Guard against recursive invocations. */ 168857429Smarkm fatal("packet_disconnect called recursively."); 168957429Smarkm disconnecting = 1; 169057429Smarkm 169157429Smarkm /* 169257429Smarkm * Format the message. Note that the caller must make sure the 169357429Smarkm * message is of limited size. 169457429Smarkm */ 169557429Smarkm va_start(args, fmt); 169657429Smarkm vsnprintf(buf, sizeof(buf), fmt, args); 169757429Smarkm va_end(args); 169857429Smarkm 1699113908Sdes /* Display the error locally */ 1700124208Sdes logit("Disconnecting: %.100s", buf); 1701113908Sdes 170257429Smarkm /* Send the disconnect message to the other side, and wait for it to get sent. */ 170360573Skris if (compat20) { 170460573Skris packet_start(SSH2_MSG_DISCONNECT); 170560573Skris packet_put_int(SSH2_DISCONNECT_PROTOCOL_ERROR); 170660573Skris packet_put_cstring(buf); 170760573Skris packet_put_cstring(""); 170860573Skris } else { 170960573Skris packet_start(SSH_MSG_DISCONNECT); 171092555Sdes packet_put_cstring(buf); 171160573Skris } 171257429Smarkm packet_send(); 171357429Smarkm packet_write_wait(); 171457429Smarkm 171557429Smarkm /* Stop listening for connections. */ 171692555Sdes channel_close_all(); 171757429Smarkm 171857429Smarkm /* Close the connection. */ 171957429Smarkm packet_close(); 1720126274Sdes cleanup_exit(255); 172157429Smarkm} 172257429Smarkm 172357429Smarkm/* Checks if there is any buffered output, and tries to write some of the output. */ 172457429Smarkm 172557429Smarkmvoid 172692555Sdespacket_write_poll(void) 172757429Smarkm{ 1728197679Sdes int len = buffer_len(&active_state->output); 1729197679Sdes int cont; 1730106121Sdes 173157429Smarkm if (len > 0) { 1732197679Sdes cont = 0; 1733197679Sdes len = roaming_write(active_state->connection_out, 1734197679Sdes buffer_ptr(&active_state->output), len, &cont); 1735181111Sdes if (len == -1) { 1736181111Sdes if (errno == EINTR || errno == EAGAIN || 1737181111Sdes errno == EWOULDBLOCK) 173857429Smarkm return; 1739181111Sdes fatal("Write failed: %.100s", strerror(errno)); 174057429Smarkm } 1741197679Sdes if (len == 0 && !cont) 1742181111Sdes fatal("Write connection closed"); 1743197679Sdes buffer_consume(&active_state->output, len); 174457429Smarkm } 174557429Smarkm} 174657429Smarkm 174757429Smarkm/* 174857429Smarkm * Calls packet_write_poll repeatedly until all pending output data has been 174957429Smarkm * written. 175057429Smarkm */ 175157429Smarkm 175257429Smarkmvoid 175392555Sdespacket_write_wait(void) 175457429Smarkm{ 175576259Sgreen fd_set *setp; 1756255767Sdes int ret, ms_remain = 0; 1757181111Sdes struct timeval start, timeout, *timeoutp = NULL; 175876259Sgreen 1759197679Sdes setp = (fd_set *)xcalloc(howmany(active_state->connection_out + 1, 1760197679Sdes NFDBITS), sizeof(fd_mask)); 176157429Smarkm packet_write_poll(); 176257429Smarkm while (packet_have_data_to_write()) { 1763197679Sdes memset(setp, 0, howmany(active_state->connection_out + 1, 1764197679Sdes NFDBITS) * sizeof(fd_mask)); 1765197679Sdes FD_SET(active_state->connection_out, setp); 1766181111Sdes 1767197679Sdes if (active_state->packet_timeout_ms > 0) { 1768197679Sdes ms_remain = active_state->packet_timeout_ms; 1769181111Sdes timeoutp = &timeout; 1770181111Sdes } 1771181111Sdes for (;;) { 1772197679Sdes if (active_state->packet_timeout_ms != -1) { 1773181111Sdes ms_to_timeval(&timeout, ms_remain); 1774181111Sdes gettimeofday(&start, NULL); 1775181111Sdes } 1776197679Sdes if ((ret = select(active_state->connection_out + 1, 1777197679Sdes NULL, setp, NULL, timeoutp)) >= 0) 1778181111Sdes break; 1779197679Sdes if (errno != EAGAIN && errno != EINTR && 1780181111Sdes errno != EWOULDBLOCK) 1781181111Sdes break; 1782197679Sdes if (active_state->packet_timeout_ms == -1) 1783181111Sdes continue; 1784181111Sdes ms_subtract_diff(&start, &ms_remain); 1785181111Sdes if (ms_remain <= 0) { 1786181111Sdes ret = 0; 1787181111Sdes break; 1788181111Sdes } 1789181111Sdes } 1790181111Sdes if (ret == 0) { 1791181111Sdes logit("Connection to %.200s timed out while " 1792181111Sdes "waiting to write", get_remote_ipaddr()); 1793181111Sdes cleanup_exit(255); 1794181111Sdes } 179557429Smarkm packet_write_poll(); 179657429Smarkm } 1797255767Sdes free(setp); 179857429Smarkm} 179957429Smarkm 180057429Smarkm/* Returns true if there is buffered data to write to the connection. */ 180157429Smarkm 180257429Smarkmint 180392555Sdespacket_have_data_to_write(void) 180457429Smarkm{ 1805197679Sdes return buffer_len(&active_state->output) != 0; 180657429Smarkm} 180757429Smarkm 180857429Smarkm/* Returns true if there is not too much data to write to the connection. */ 180957429Smarkm 181057429Smarkmint 181192555Sdespacket_not_very_much_data_to_write(void) 181257429Smarkm{ 1813197679Sdes if (active_state->interactive_mode) 1814197679Sdes return buffer_len(&active_state->output) < 16384; 181557429Smarkm else 1816197679Sdes return buffer_len(&active_state->output) < 128 * 1024; 181757429Smarkm} 181857429Smarkm 1819113908Sdesstatic void 1820221420Sdespacket_set_tos(int tos) 1821113908Sdes{ 1822226046Sdes#ifndef IP_TOS_IS_BROKEN 1823226046Sdes if (!packet_connection_is_on_socket()) 1824113908Sdes return; 1825226046Sdes switch (packet_connection_af()) { 1826226046Sdes# ifdef IP_TOS 1827226046Sdes case AF_INET: 1828226046Sdes debug3("%s: set IP_TOS 0x%02x", __func__, tos); 1829226046Sdes if (setsockopt(active_state->connection_in, 1830226046Sdes IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) 1831226046Sdes error("setsockopt IP_TOS %d: %.100s:", 1832226046Sdes tos, strerror(errno)); 1833226046Sdes break; 1834226046Sdes# endif /* IP_TOS */ 1835226046Sdes# ifdef IPV6_TCLASS 1836226046Sdes case AF_INET6: 1837226046Sdes debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos); 1838226046Sdes if (setsockopt(active_state->connection_in, 1839226046Sdes IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0) 1840226046Sdes error("setsockopt IPV6_TCLASS %d: %.100s:", 1841226046Sdes tos, strerror(errno)); 1842226046Sdes break; 1843226046Sdes# endif /* IPV6_TCLASS */ 1844226046Sdes } 1845226046Sdes#endif /* IP_TOS_IS_BROKEN */ 1846113908Sdes} 1847113908Sdes 184857429Smarkm/* Informs that the current session is interactive. Sets IP flags for that. */ 184957429Smarkm 185057429Smarkmvoid 1851221420Sdespacket_set_interactive(int interactive, int qos_interactive, int qos_bulk) 185257429Smarkm{ 1853197679Sdes if (active_state->set_interactive_called) 185476259Sgreen return; 1855197679Sdes active_state->set_interactive_called = 1; 185676259Sgreen 185757429Smarkm /* Record that we are in interactive mode. */ 1858197679Sdes active_state->interactive_mode = interactive; 185957429Smarkm 186057429Smarkm /* Only set socket options if using a socket. */ 186157429Smarkm if (!packet_connection_is_on_socket()) 1862116791Sdes return; 1863197679Sdes set_nodelay(active_state->connection_in); 1864221420Sdes packet_set_tos(interactive ? qos_interactive : qos_bulk); 186557429Smarkm} 186657429Smarkm 186757429Smarkm/* Returns true if the current connection is interactive. */ 186857429Smarkm 186957429Smarkmint 187092555Sdespacket_is_interactive(void) 187157429Smarkm{ 1872197679Sdes return active_state->interactive_mode; 187357429Smarkm} 187457429Smarkm 1875137015Sdesint 1876124208Sdespacket_set_maxsize(u_int s) 187757429Smarkm{ 1878197679Sdes if (active_state->set_maxsize_called) { 1879124208Sdes logit("packet_set_maxsize: called twice: old %d new %d", 1880197679Sdes active_state->max_packet_size, s); 188157429Smarkm return -1; 188257429Smarkm } 188357429Smarkm if (s < 4 * 1024 || s > 1024 * 1024) { 1884124208Sdes logit("packet_set_maxsize: bad size %d", s); 188557429Smarkm return -1; 188657429Smarkm } 1887197679Sdes active_state->set_maxsize_called = 1; 188892555Sdes debug("packet_set_maxsize: setting to %d", s); 1889197679Sdes active_state->max_packet_size = s; 189057429Smarkm return s; 189157429Smarkm} 189276259Sgreen 1893197679Sdesint 1894197679Sdespacket_inc_alive_timeouts(void) 1895197679Sdes{ 1896197679Sdes return ++active_state->keep_alive_timeouts; 1897197679Sdes} 1898197679Sdes 1899197679Sdesvoid 1900197679Sdespacket_set_alive_timeouts(int ka) 1901197679Sdes{ 1902197679Sdes active_state->keep_alive_timeouts = ka; 1903197679Sdes} 1904197679Sdes 1905197679Sdesu_int 1906197679Sdespacket_get_maxsize(void) 1907197679Sdes{ 1908197679Sdes return active_state->max_packet_size; 1909197679Sdes} 1910197679Sdes 191192555Sdes/* roundup current message to pad bytes */ 191292555Sdesvoid 191392555Sdespacket_add_padding(u_char pad) 191492555Sdes{ 1915197679Sdes active_state->extra_pad = pad; 191692555Sdes} 191792555Sdes 191876259Sgreen/* 191976259Sgreen * 9.2. Ignored Data Message 192076259Sgreen * 192176259Sgreen * byte SSH_MSG_IGNORE 192276259Sgreen * string data 192376259Sgreen * 192476259Sgreen * All implementations MUST understand (and ignore) this message at any 192576259Sgreen * time (after receiving the protocol version). No implementation is 192676259Sgreen * required to send them. This message can be used as an additional 192776259Sgreen * protection measure against advanced traffic analysis techniques. 192876259Sgreen */ 192976259Sgreenvoid 193076259Sgreenpacket_send_ignore(int nbytes) 193176259Sgreen{ 1932137015Sdes u_int32_t rnd = 0; 193376259Sgreen int i; 193476259Sgreen 193576259Sgreen packet_start(compat20 ? SSH2_MSG_IGNORE : SSH_MSG_IGNORE); 193676259Sgreen packet_put_int(nbytes); 193792555Sdes for (i = 0; i < nbytes; i++) { 193876259Sgreen if (i % 4 == 0) 1939137015Sdes rnd = arc4random(); 1940162852Sdes packet_put_char((u_char)rnd & 0xff); 1941137015Sdes rnd >>= 8; 194276259Sgreen } 194376259Sgreen} 1944124208Sdes 1945224638Sbrooks#ifdef NONE_CIPHER_ENABLED 1946224638Sbrooksvoid 1947224638Sbrookspacket_request_rekeying(void) 1948224638Sbrooks{ 1949224638Sbrooks rekey_requested = 1; 1950224638Sbrooks} 1951224638Sbrooks#endif 1952224638Sbrooks 1953137015Sdes#define MAX_PACKETS (1U<<31) 1954124208Sdesint 1955124208Sdespacket_need_rekeying(void) 1956124208Sdes{ 1957124208Sdes if (datafellows & SSH_BUG_NOREKEY) 1958124208Sdes return 0; 1959224638Sbrooks#ifdef NONE_CIPHER_ENABLED 1960224638Sbrooks if (rekey_requested == 1) { 1961224638Sbrooks rekey_requested = 0; 1962224638Sbrooks return 1; 1963224638Sbrooks } 1964224638Sbrooks#endif 1965124208Sdes return 1966197679Sdes (active_state->p_send.packets > MAX_PACKETS) || 1967197679Sdes (active_state->p_read.packets > MAX_PACKETS) || 1968197679Sdes (active_state->max_blocks_out && 1969197679Sdes (active_state->p_send.blocks > active_state->max_blocks_out)) || 1970197679Sdes (active_state->max_blocks_in && 1971255767Sdes (active_state->p_read.blocks > active_state->max_blocks_in)) || 1972255767Sdes (active_state->rekey_interval != 0 && active_state->rekey_time + 1973255767Sdes active_state->rekey_interval <= monotime()); 1974124208Sdes} 1975124208Sdes 1976124208Sdesvoid 1977255767Sdespacket_set_rekey_limits(u_int32_t bytes, time_t seconds) 1978124208Sdes{ 1979255767Sdes debug3("rekey after %lld bytes, %d seconds", (long long)bytes, 1980255767Sdes (int)seconds); 1981197679Sdes active_state->rekey_limit = bytes; 1982255767Sdes active_state->rekey_interval = seconds; 1983255767Sdes /* 1984255767Sdes * We set the time here so that in post-auth privsep slave we count 1985255767Sdes * from the completion of the authentication. 1986255767Sdes */ 1987255767Sdes active_state->rekey_time = monotime(); 1988124208Sdes} 1989149749Sdes 1990255767Sdestime_t 1991255767Sdespacket_get_rekey_timeout(void) 1992255767Sdes{ 1993255767Sdes time_t seconds; 1994255767Sdes 1995255767Sdes seconds = active_state->rekey_time + active_state->rekey_interval - 1996255767Sdes monotime(); 1997255767Sdes return (seconds <= 0 ? 1 : seconds); 1998255767Sdes} 1999255767Sdes 2000149749Sdesvoid 2001149749Sdespacket_set_server(void) 2002149749Sdes{ 2003197679Sdes active_state->server_side = 1; 2004149749Sdes} 2005149749Sdes 2006149749Sdesvoid 2007149749Sdespacket_set_authenticated(void) 2008149749Sdes{ 2009197679Sdes active_state->after_authentication = 1; 2010149749Sdes} 2011197679Sdes 2012197679Sdesvoid * 2013197679Sdespacket_get_input(void) 2014197679Sdes{ 2015197679Sdes return (void *)&active_state->input; 2016197679Sdes} 2017197679Sdes 2018197679Sdesvoid * 2019197679Sdespacket_get_output(void) 2020197679Sdes{ 2021197679Sdes return (void *)&active_state->output; 2022197679Sdes} 2023197679Sdes 2024197679Sdesvoid * 2025197679Sdespacket_get_newkeys(int mode) 2026197679Sdes{ 2027197679Sdes return (void *)active_state->newkeys[mode]; 2028197679Sdes} 2029197679Sdes 2030197679Sdes/* 2031197679Sdes * Save the state for the real connection, and use a separate state when 2032197679Sdes * resuming a suspended connection. 2033197679Sdes */ 2034197679Sdesvoid 2035197679Sdespacket_backup_state(void) 2036197679Sdes{ 2037197679Sdes struct session_state *tmp; 2038197679Sdes 2039197679Sdes close(active_state->connection_in); 2040197679Sdes active_state->connection_in = -1; 2041197679Sdes close(active_state->connection_out); 2042197679Sdes active_state->connection_out = -1; 2043197679Sdes if (backup_state) 2044197679Sdes tmp = backup_state; 2045197679Sdes else 2046197679Sdes tmp = alloc_session_state(); 2047197679Sdes backup_state = active_state; 2048197679Sdes active_state = tmp; 2049197679Sdes} 2050197679Sdes 2051197679Sdes/* 2052197679Sdes * Swap in the old state when resuming a connecion. 2053197679Sdes */ 2054197679Sdesvoid 2055197679Sdespacket_restore_state(void) 2056197679Sdes{ 2057197679Sdes struct session_state *tmp; 2058197679Sdes void *buf; 2059197679Sdes u_int len; 2060197679Sdes 2061197679Sdes tmp = backup_state; 2062197679Sdes backup_state = active_state; 2063197679Sdes active_state = tmp; 2064197679Sdes active_state->connection_in = backup_state->connection_in; 2065197679Sdes backup_state->connection_in = -1; 2066197679Sdes active_state->connection_out = backup_state->connection_out; 2067197679Sdes backup_state->connection_out = -1; 2068197679Sdes len = buffer_len(&backup_state->input); 2069197679Sdes if (len > 0) { 2070197679Sdes buf = buffer_ptr(&backup_state->input); 2071197679Sdes buffer_append(&active_state->input, buf, len); 2072197679Sdes buffer_clear(&backup_state->input); 2073197679Sdes add_recv_bytes(len); 2074197679Sdes } 2075197679Sdes} 2076224638Sbrooks 2077224638Sbrooks#ifdef NONE_CIPHER_ENABLED 2078224638Sbrooksint 2079224638Sbrookspacket_get_authentication_state(void) 2080224638Sbrooks{ 2081224638Sbrooks return (active_state->after_authentication); 2082224638Sbrooks} 2083224638Sbrooks#endif 2084