⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packet.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland *                    All rights reserved * This file contains code implementing the packet protocol and communication * with the other side.  This same code is used both on client and server side. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose.  Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * * SSH2 packet format added by Markus Friedl. * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "includes.h"RCSID("$OpenBSD: packet.c,v 1.95 2002/06/19 18:01:00 markus Exp $");#include "xmalloc.h"#include "buffer.h"#include "packet.h"#include "bufaux.h"#include "crc32.h"#include "getput.h"#include "compress.h"#include "deattack.h"#include "channels.h"#include "compat.h"#include "ssh1.h"#include "ssh2.h"#include "cipher.h"#include "kex.h"#include "mac.h"#include "log.h"#include "canohost.h"#include "misc.h"#include "ssh.h"#ifdef PACKET_DEBUG#define DBG(x) x#else#define DBG(x)#endif/* * This variable contains the file descriptors used for communicating with * the other side.  connection_in is used for reading; connection_out for * writing.  These can be the same descriptor, in which case it is assumed to * be a socket. */static int connection_in = -1;static int connection_out = -1;/* Protocol flags for the remote side. */static u_int remote_protocol_flags = 0;/* Encryption context for receiving data.  This is only used for decryption. */static CipherContext receive_context;/* Encryption context for sending data.  This is only used for encryption. */static CipherContext send_context;/* Buffer for raw input data from the socket. */Buffer input;/* Buffer for raw output data going to the socket. */Buffer output;/* Buffer for the partial outgoing packet being constructed. */static Buffer outgoing_packet;/* Buffer for the incoming packet currently being processed. */static Buffer incoming_packet;/* Scratch buffer for packet compression/decompression. */static Buffer compression_buffer;static int compression_buffer_ready = 0;/* Flag indicating whether packet compression/decompression is enabled. */static int packet_compression = 0;/* default maximum packet size */int max_packet_size = 32768;/* Flag indicating whether this module has been initialized. */static int initialized = 0;/* Set to true if the connection is interactive. */static int interactive_mode = 0;/* Session key information for Encryption and MAC */Newkeys *newkeys[MODE_MAX];static u_int32_t read_seqnr = 0;static u_int32_t send_seqnr = 0;/* Session key for protocol v1 */static u_char ssh1_key[SSH_SESSION_KEY_LENGTH];static u_int ssh1_keylen;/* roundup current message to extra_pad bytes */static u_char extra_pad = 0;/* * Sets the descriptors used for communication.  Disables encryption until * packet_set_encryption_key is called. */voidpacket_set_connection(int fd_in, int fd_out){	Cipher *none = cipher_by_name("none");	if (none == NULL)		fatal("packet_set_connection: cannot load cipher 'none'");	connection_in = fd_in;	connection_out = fd_out;	cipher_init(&send_context, none, "", 0, NULL, 0, CIPHER_ENCRYPT);	cipher_init(&receive_context, none, "", 0, NULL, 0, CIPHER_DECRYPT);	newkeys[MODE_IN] = newkeys[MODE_OUT] = NULL;	if (!initialized) {		initialized = 1;		buffer_init(&input);		buffer_init(&output);		buffer_init(&outgoing_packet);		buffer_init(&incoming_packet);	}	/* Kludge: arrange the close function to be called from fatal(). */	fatal_add_cleanup((void (*) (void *)) packet_close, NULL);}/* Returns 1 if remote host is connected via socket, 0 if not. */intpacket_connection_is_on_socket(void){	struct sockaddr_storage from, to;	socklen_t fromlen, tolen;	/* filedescriptors in and out are the same, so it's a socket */	if (connection_in == connection_out)		return 1;	fromlen = sizeof(from);	memset(&from, 0, sizeof(from));	if (getpeername(connection_in, (struct sockaddr *)&from, &fromlen) < 0)		return 0;	tolen = sizeof(to);	memset(&to, 0, sizeof(to));	if (getpeername(connection_out, (struct sockaddr *)&to, &tolen) < 0)		return 0;	if (fromlen != tolen || memcmp(&from, &to, fromlen) != 0)		return 0;	if (from.ss_family != AF_INET && from.ss_family != AF_INET6)		return 0;	return 1;}/* * Exports an IV from the CipherContext required to export the key * state back from the unprivileged child to the privileged parent * process. */voidpacket_get_keyiv(int mode, u_char *iv, u_int len){	CipherContext *cc;	if (mode == MODE_OUT)		cc = &send_context;	else		cc = &receive_context;	cipher_get_keyiv(cc, iv, len);}intpacket_get_keycontext(int mode, u_char *dat){	CipherContext *cc;	if (mode == MODE_OUT)		cc = &send_context;	else		cc = &receive_context;	return (cipher_get_keycontext(cc, dat));}voidpacket_set_keycontext(int mode, u_char *dat){	CipherContext *cc;	if (mode == MODE_OUT)		cc = &send_context;	else		cc = &receive_context;	cipher_set_keycontext(cc, dat);}intpacket_get_keyiv_len(int mode){	CipherContext *cc;	if (mode == MODE_OUT)		cc = &send_context;	else		cc = &receive_context;	return (cipher_get_keyiv_len(cc));}voidpacket_set_iv(int mode, u_char *dat){	CipherContext *cc;	if (mode == MODE_OUT)		cc = &send_context;	else		cc = &receive_context;	cipher_set_keyiv(cc, dat);}intpacket_get_ssh1_cipher(){	return (cipher_get_number(receive_context.cipher));}u_int32_tpacket_get_seqnr(int mode){	return (mode == MODE_IN ? read_seqnr : send_seqnr);}voidpacket_set_seqnr(int mode, u_int32_t seqnr){	if (mode == MODE_IN)		read_seqnr = seqnr;	else if (mode == MODE_OUT)		send_seqnr = seqnr;	else		fatal("packet_set_seqnr: bad mode %d", mode);}/* returns 1 if connection is via ipv4 */intpacket_connection_is_ipv4(void){	struct sockaddr_storage to;	socklen_t tolen = sizeof(to);	memset(&to, 0, sizeof(to));	if (getsockname(connection_out, (struct sockaddr *)&to, &tolen) < 0)		return 0;	if (to.ss_family == AF_INET)		return 1;#ifdef IPV4_IN_IPV6	if (to.ss_family == AF_INET6 && 	    IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))		return 1;#endif	return 0;}/* Sets the connection into non-blocking mode. */voidpacket_set_nonblocking(void){	/* Set the socket into non-blocking mode. */	if (fcntl(connection_in, F_SETFL, O_NONBLOCK) < 0)		error("fcntl O_NONBLOCK: %.100s", strerror(errno));	if (connection_out != connection_in) {		if (fcntl(connection_out, F_SETFL, O_NONBLOCK) < 0)			error("fcntl O_NONBLOCK: %.100s", strerror(errno));	}}/* Returns the socket used for reading. */intpacket_get_connection_in(void){	return connection_in;}/* Returns the descriptor used for writing. */intpacket_get_connection_out(void){	return connection_out;}/* Closes the connection and clears and frees internal data structures. */voidpacket_close(void){	if (!initialized)		return;	initialized = 0;	if (connection_in == connection_out) {		shutdown(connection_out, SHUT_RDWR);		close(connection_out);	} else {		close(connection_in);		close(connection_out);	}	buffer_free(&input);	buffer_free(&output);	buffer_free(&outgoing_packet);	buffer_free(&incoming_packet);	if (compression_buffer_ready) {		buffer_free(&compression_buffer);		buffer_compress_uninit();	}	cipher_cleanup(&send_context);	cipher_cleanup(&receive_context);}/* Sets remote side protocol flags. */voidpacket_set_protocol_flags(u_int protocol_flags){	remote_protocol_flags = protocol_flags;}/* Returns the remote protocol flags set earlier by the above function. */u_intpacket_get_protocol_flags(void){	return remote_protocol_flags;}/* * Starts packet compression from the next packet on in both directions. * Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */static voidpacket_init_compression(void){	if (compression_buffer_ready == 1)		return;	compression_buffer_ready = 1;	buffer_init(&compression_buffer);}voidpacket_start_compression(int level){	if (packet_compression && !compat20)		fatal("Compression already enabled.");	packet_compression = 1;	packet_init_compression();	buffer_compress_init_send(level);	buffer_compress_init_recv();}/* * Causes any further packets to be encrypted using the given key.  The same * key is used for both sending and reception.  However, both directions are * encrypted independently of each other. */voidpacket_set_encryption_key(const u_char *key, u_int keylen,    int number){	Cipher *cipher = cipher_by_number(number);	if (cipher == NULL)		fatal("packet_set_encryption_key: unknown cipher number %d", number);	if (keylen < 20)		fatal("packet_set_encryption_key: keylen too small: %d", keylen);	if (keylen > SSH_SESSION_KEY_LENGTH)		fatal("packet_set_encryption_key: keylen too big: %d", keylen);	memcpy(ssh1_key, key, keylen);	ssh1_keylen = keylen;	cipher_init(&send_context, cipher, key, keylen, NULL, 0, CIPHER_ENCRYPT);	cipher_init(&receive_context, cipher, key, keylen, NULL, 0, CIPHER_DECRYPT);}u_intpacket_get_encryption_key(u_char *key){	if (key == NULL)		return (ssh1_keylen);	memcpy(key, ssh1_key, ssh1_keylen);	return (ssh1_keylen);}/* Start constructing a packet to send. */voidpacket_start(u_char type){	u_char buf[9];	int len;	DBG(debug("packet_start[%d]", type));	len = compat20 ? 6 : 9;	memset(buf, 0, len - 1);	buf[len - 1] = type;	buffer_clear(&outgoing_packet);	buffer_append(&outgoing_packet, buf, len);}/* Append payload. */voidpacket_put_char(int value){	char ch = value;	buffer_append(&outgoing_packet, &ch, 1);}voidpacket_put_int(u_int value){	buffer_put_int(&outgoing_packet, value);}voidpacket_put_string(const void *buf, u_int len){	buffer_put_string(&outgoing_packet, buf, len);}voidpacket_put_cstring(const char *str){	buffer_put_cstring(&outgoing_packet, str);}voidpacket_put_raw(const void *buf, u_int len){	buffer_append(&outgoing_packet, buf, len);}voidpacket_put_bignum(BIGNUM * value){	buffer_put_bignum(&outgoing_packet, value);}void

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -