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

📄 packet.c

📁 OpenSSL Source code for SFTP, SSH, and many others
💻 C
📖 第 1 页 / 共 3 页
字号:
packet_put_bignum2(BIGNUM * value){	buffer_put_bignum2(&outgoing_packet, value);}/* * Finalizes and sends the packet.  If the encryption key has been set, * encrypts the packet before sending. */static voidpacket_send1(void){	u_char buf[8], *cp;	int i, padding, len;	u_int checksum;	u_int32_t rand = 0;	/*	 * If using packet compression, compress the payload of the outgoing	 * packet.	 */	if (packet_compression) {		buffer_clear(&compression_buffer);		/* Skip padding. */		buffer_consume(&outgoing_packet, 8);		/* padding */		buffer_append(&compression_buffer, "\0\0\0\0\0\0\0\0", 8);		buffer_compress(&outgoing_packet, &compression_buffer);		buffer_clear(&outgoing_packet);		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),		    buffer_len(&compression_buffer));	}	/* Compute packet length without padding (add checksum, remove padding). */	len = buffer_len(&outgoing_packet) + 4 - 8;	/* Insert padding. Initialized to zero in packet_start1() */	padding = 8 - len % 8;	if (!send_context.plaintext) {		cp = buffer_ptr(&outgoing_packet);		for (i = 0; i < padding; i++) {			if (i % 4 == 0)				rand = arc4random();			cp[7 - i] = rand & 0xff;			rand >>= 8;		}	}	buffer_consume(&outgoing_packet, 8 - padding);	/* Add check bytes. */	checksum = ssh_crc32(buffer_ptr(&outgoing_packet),	    buffer_len(&outgoing_packet));	PUT_32BIT(buf, checksum);	buffer_append(&outgoing_packet, buf, 4);#ifdef PACKET_DEBUG	fprintf(stderr, "packet_send plain: ");	buffer_dump(&outgoing_packet);#endif	/* Append to output. */	PUT_32BIT(buf, len);	buffer_append(&output, buf, 4);	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),	    buffer_len(&outgoing_packet));#ifdef PACKET_DEBUG	fprintf(stderr, "encrypted: ");	buffer_dump(&output);#endif	buffer_clear(&outgoing_packet);	/*	 * Note that the packet is now only buffered in output.  It won\'t be	 * actually sent until packet_write_wait or packet_write_poll is	 * called.	 */}voidset_newkeys(int mode){	Enc *enc;	Mac *mac;	Comp *comp;	CipherContext *cc;	int encrypt;	debug("newkeys: mode %d", mode);	if (mode == MODE_OUT) {		cc = &send_context;		encrypt = CIPHER_ENCRYPT;	} else {		cc = &receive_context;		encrypt = CIPHER_DECRYPT;	}	if (newkeys[mode] != NULL) {		debug("newkeys: rekeying");		cipher_cleanup(cc);		enc  = &newkeys[mode]->enc;		mac  = &newkeys[mode]->mac;		comp = &newkeys[mode]->comp;		memset(mac->key, 0, mac->key_len);		xfree(enc->name);		xfree(enc->iv);		xfree(enc->key);		xfree(mac->name);		xfree(mac->key);		xfree(comp->name);		xfree(newkeys[mode]);	}	newkeys[mode] = kex_get_newkeys(mode);	if (newkeys[mode] == NULL)		fatal("newkeys: no keys for mode %d", mode);	enc  = &newkeys[mode]->enc;	mac  = &newkeys[mode]->mac;	comp = &newkeys[mode]->comp;	if (mac->md != NULL)		mac->enabled = 1;	DBG(debug("cipher_init_context: %d", mode));	cipher_init(cc, enc->cipher, enc->key, enc->key_len,	    enc->iv, enc->block_size, encrypt);	/* Deleting the keys does not gain extra security */	/* memset(enc->iv,  0, enc->block_size);	   memset(enc->key, 0, enc->key_len); */	if (comp->type != 0 && comp->enabled == 0) {		packet_init_compression();		if (mode == MODE_OUT)			buffer_compress_init_send(6);		else			buffer_compress_init_recv();		comp->enabled = 1;	}}/* * Finalize packet in SSH2 format (compress, mac, encrypt, enqueue) */static voidpacket_send2(void){	u_char type, *cp, *macbuf = NULL;	u_char padlen, pad;	u_int packet_length = 0;	u_int i, len;	u_int32_t rand = 0;	Enc *enc   = NULL;	Mac *mac   = NULL;	Comp *comp = NULL;	int block_size;	if (newkeys[MODE_OUT] != NULL) {		enc  = &newkeys[MODE_OUT]->enc;		mac  = &newkeys[MODE_OUT]->mac;		comp = &newkeys[MODE_OUT]->comp;	}	block_size = enc ? enc->block_size : 8;	cp = buffer_ptr(&outgoing_packet);	type = cp[5];#ifdef PACKET_DEBUG	fprintf(stderr, "plain:     ");	buffer_dump(&outgoing_packet);#endif	if (comp && comp->enabled) {		len = buffer_len(&outgoing_packet);		/* skip header, compress only payload */		buffer_consume(&outgoing_packet, 5);		buffer_clear(&compression_buffer);		buffer_compress(&outgoing_packet, &compression_buffer);		buffer_clear(&outgoing_packet);		buffer_append(&outgoing_packet, "\0\0\0\0\0", 5);		buffer_append(&outgoing_packet, buffer_ptr(&compression_buffer),		    buffer_len(&compression_buffer));		DBG(debug("compression: raw %d compressed %d", len,		    buffer_len(&outgoing_packet)));	}	/* sizeof (packet_len + pad_len + payload) */	len = buffer_len(&outgoing_packet);	/*	 * calc size of padding, alloc space, get random data,	 * minimum padding is 4 bytes	 */	padlen = block_size - (len % block_size);	if (padlen < 4)		padlen += block_size;	if (extra_pad) {		/* will wrap if extra_pad+padlen > 255 */		extra_pad  = roundup(extra_pad, block_size);		pad = extra_pad - ((len + padlen) % extra_pad);		debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)",		    pad, len, padlen, extra_pad);		padlen += pad;		extra_pad = 0;	}	cp = buffer_append_space(&outgoing_packet, padlen);	if (enc && !send_context.plaintext) {		/* random padding */		for (i = 0; i < padlen; i++) {			if (i % 4 == 0)				rand = arc4random();			cp[i] = rand & 0xff;			rand >>= 8;		}	} else {		/* clear padding */		memset(cp, 0, padlen);	}	/* packet_length includes payload, padding and padding length field */	packet_length = buffer_len(&outgoing_packet) - 4;	cp = buffer_ptr(&outgoing_packet);	PUT_32BIT(cp, packet_length);	cp[4] = padlen;	DBG(debug("send: len %d (includes padlen %d)", packet_length+4, padlen));	/* compute MAC over seqnr and packet(length fields, payload, padding) */	if (mac && mac->enabled) {		macbuf = mac_compute(mac, send_seqnr,		    buffer_ptr(&outgoing_packet),		    buffer_len(&outgoing_packet));		DBG(debug("done calc MAC out #%d", send_seqnr));	}	/* encrypt packet and append to output buffer. */	cp = buffer_append_space(&output, buffer_len(&outgoing_packet));	cipher_crypt(&send_context, cp, buffer_ptr(&outgoing_packet),	    buffer_len(&outgoing_packet));	/* append unencrypted MAC */	if (mac && mac->enabled)		buffer_append(&output, (char *)macbuf, mac->mac_len);#ifdef PACKET_DEBUG	fprintf(stderr, "encrypted: ");	buffer_dump(&output);#endif	/* increment sequence number for outgoing packets */	if (++send_seqnr == 0)		log("outgoing seqnr wraps around");	buffer_clear(&outgoing_packet);	if (type == SSH2_MSG_NEWKEYS)		set_newkeys(MODE_OUT);}voidpacket_send(void){	if (compat20)		packet_send2();	else		packet_send1();	DBG(debug("packet_send done"));}/* * Waits until a packet has been received, and returns its type.  Note that * no other data is processed until this returns, so this function should not * be used during the interactive session. */intpacket_read_seqnr(u_int32_t *seqnr_p){	int type, len;	fd_set *setp;	char buf[8192];	DBG(debug("packet_read()"));	setp = (fd_set *)xmalloc(howmany(connection_in+1, NFDBITS) *	    sizeof(fd_mask));	/* Since we are blocking, ensure that all written packets have been sent. */	packet_write_wait();	/* Stay in the loop until we have received a complete packet. */	for (;;) {		/* Try to read a packet from the buffer. */		type = packet_read_poll_seqnr(seqnr_p);		if (!compat20 && (		    type == SSH_SMSG_SUCCESS		    || type == SSH_SMSG_FAILURE		    || type == SSH_CMSG_EOF		    || type == SSH_CMSG_EXIT_CONFIRMATION))			packet_check_eom();		/* If we got a packet, return it. */		if (type != SSH_MSG_NONE) {			xfree(setp);			return type;		}		/*		 * Otherwise, wait for some data to arrive, add it to the		 * buffer, and try again.		 */		memset(setp, 0, howmany(connection_in + 1, NFDBITS) *		    sizeof(fd_mask));		FD_SET(connection_in, setp);		/* Wait for some data to arrive. */		while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 &&		    (errno == EAGAIN || errno == EINTR))			;		/* Read data from the socket. */		len = read(connection_in, buf, sizeof(buf));		if (len == 0) {			log("Connection closed by %.200s", get_remote_ipaddr());			fatal_cleanup();		}		if (len < 0)			fatal("Read from socket failed: %.100s", strerror(errno));		/* Append it to the buffer. */		packet_process_incoming(buf, len);	}	/* NOTREACHED */}intpacket_read(void){	return packet_read_seqnr(NULL);}/* * Waits until a packet has been received, verifies that its type matches * that given, and gives a fatal error and exits if there is a mismatch. */voidpacket_read_expect(int expected_type){	int type;	type = packet_read();	if (type != expected_type)		packet_disconnect("Protocol error: expected packet type %d, got %d",		    expected_type, type);}/* Checks if a full packet is available in the data received so far via * packet_process_incoming.  If so, reads the packet; otherwise returns * SSH_MSG_NONE.  This does not wait for data from the connection. * * SSH_MSG_DISCONNECT is handled specially here.  Also, * SSH_MSG_IGNORE messages are skipped by this function and are never returned * to higher levels. */static intpacket_read_poll1(void){	u_int len, padded_len;	u_char *cp, type;	u_int checksum, stored_checksum;	/* Check if input size is less than minimum packet size. */	if (buffer_len(&input) < 4 + 8)		return SSH_MSG_NONE;	/* Get length of incoming packet. */	cp = buffer_ptr(&input);	len = GET_32BIT(cp);	if (len < 1 + 2 + 2 || len > 256 * 1024)		packet_disconnect("Bad packet length %d.", len);	padded_len = (len + 8) & ~7;	/* Check if the packet has been entirely received. */	if (buffer_len(&input) < 4 + padded_len)		return SSH_MSG_NONE;	/* The entire packet is in buffer. */	/* Consume packet length. */	buffer_consume(&input, 4);	/*	 * Cryptographic attack detector for ssh	 * (C)1998 CORE-SDI, Buenos Aires Argentina	 * Ariel Futoransky(futo@core-sdi.com)	 */	if (!receive_context.plaintext &&	    detect_attack(buffer_ptr(&input), padded_len, NULL) == DEATTACK_DETECTED)		packet_disconnect("crc32 compensation attack: network attack detected");	/* Decrypt data to incoming_packet. */	buffer_clear(&incoming_packet);	cp = buffer_append_space(&incoming_packet, padded_len);	cipher_crypt(&receive_context, cp, buffer_ptr(&input), padded_len);	buffer_consume(&input, padded_len);#ifdef PACKET_DEBUG	fprintf(stderr, "read_poll plain: ");	buffer_dump(&incoming_packet);#endif	/* Compute packet checksum. */	checksum = ssh_crc32(buffer_ptr(&incoming_packet),	    buffer_len(&incoming_packet) - 4);	/* Skip padding. */	buffer_consume(&incoming_packet, 8 - len % 8);	/* Test check bytes. */	if (len != buffer_len(&incoming_packet))		packet_disconnect("packet_read_poll1: len %d != buffer_len %d.",		    len, buffer_len(&incoming_packet));	cp = (u_char *)buffer_ptr(&incoming_packet) + len - 4;	stored_checksum = GET_32BIT(cp);	if (checksum != stored_checksum)		packet_disconnect("Corrupted check bytes on input.");	buffer_consume_end(&incoming_packet, 4);	if (packet_compression) {		buffer_clear(&compression_buffer);		buffer_uncompress(&incoming_packet, &compression_buffer);		buffer_clear(&incoming_packet);		buffer_append(&incoming_packet, buffer_ptr(&compression_buffer),		    buffer_len(&compression_buffer));	}	type = buffer_get_char(&incoming_packet);	return type;}static intpacket_read_poll2(u_int32_t *seqnr_p){	static u_int packet_length = 0;	u_int padlen, need;	u_char *macbuf, *cp, type;	int maclen, block_size;	Enc *enc   = NULL;	Mac *mac   = NULL;	Comp *comp = NULL;	if (newkeys[MODE_IN] != NULL) {		enc  = &newkeys[MODE_IN]->enc;		mac  = &newkeys[MODE_IN]->mac;		comp = &newkeys[MODE_IN]->comp;	}	maclen = mac && mac->enabled ? mac->mac_len : 0;	block_size = enc ? enc->block_size : 8;	if (packet_length == 0) {		/*		 * check if input size is less than the cipher block size,		 * decrypt first block and extract length of incoming packet		 */		if (buffer_len(&input) < block_size)			return SSH_MSG_NONE;		buffer_clear(&incoming_packet);		cp = buffer_append_space(&incoming_packet, block_size);		cipher_crypt(&receive_context, cp, buffer_ptr(&input),		    block_size);		cp = buffer_ptr(&incoming_packet);		packet_length = GET_32BIT(cp);		if (packet_length < 1 + 4 || packet_length > 256 * 1024) {			buffer_dump(&incoming_packet);			packet_disconnect("Bad packet length %d.", packet_length);		}		DBG(debug("input: packet len %d", packet_length+4));		buffer_consume(&input, block_size);	}	/* we have a partial packet of block_size bytes */	need = 4 + packet_length - block_size;	DBG(debug("partial packet %d, need %d, maclen %d", block_size,	    need, maclen));	if (need % block_size != 0)		fatal("padding error: need %d block %d mod %d",

⌨️ 快捷键说明

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