mirror of
				https://github.com/clearml/dropbear
				synced 2025-06-26 18:17:32 +00:00 
			
		
		
		
	Prevent invalid packets being sent during key-exchange, instead queue
them until afterwards. This could sometimes terminate connections after 8 hours if (for example) a new TCP forwarded connection was sent at the KEX timeout. --HG-- extra : convert_revision : 48426bd66b8f5ba50045f7ba190d1672745132e2
This commit is contained in:
		
							parent
							
								
									993f58900d
								
							
						
					
					
						commit
						57ae0bfedf
					
				| @ -80,9 +80,12 @@ void common_session_init(int sock, char* remotehost) { | ||||
| 	initqueue(&ses.writequeue); | ||||
| 
 | ||||
| 	ses.requirenext = SSH_MSG_KEXINIT; | ||||
| 	ses.dataallowed = 0; /* don't send data yet, we'll wait until after kex */ | ||||
| 	ses.dataallowed = 1; /* we can send data until we actually 
 | ||||
| 							send the SSH_MSG_KEXINIT */ | ||||
| 	ses.ignorenext = 0; | ||||
| 	ses.lastpacket = 0; | ||||
| 	ses.reply_queue_head = NULL; | ||||
| 	ses.reply_queue_tail = NULL; | ||||
| 
 | ||||
| 	/* set all the algos to none */ | ||||
| 	ses.keys = (struct key_context*)m_malloc(sizeof(struct key_context)); | ||||
| @ -193,6 +196,10 @@ void session_loop(void(*loophandler)()) { | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		/* if required, flush out any queued reply packets that
 | ||||
| 		were being held up during a KEX */ | ||||
| 		maybe_flush_reply_queue(); | ||||
| 
 | ||||
| 		/* process pipes etc for the channels, ses.dataallowed == 0
 | ||||
| 		 * during rekeying ) */ | ||||
| 		if (ses.dataallowed) { | ||||
|  | ||||
							
								
								
									
										66
									
								
								packet.c
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								packet.c
									
									
									
									
									
								
							| @ -403,7 +403,60 @@ static buffer* buf_decompress(buffer* buf, unsigned int len) { | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| /* returns 1 if the packet is a valid type during kex (see 7.1 of rfc4253) */ | ||||
| static int packet_is_okay_kex(unsigned char type) { | ||||
| 	if (type >= SSH_MSG_USERAUTH_REQUEST) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (type == SSH_MSG_SERVICE_REQUEST || type == SSH_MSG_SERVICE_ACCEPT) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if (type == SSH_MSG_KEXINIT) { | ||||
| 		/* XXX should this die horribly if !dataallowed ?? */ | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static void enqueue_reply_packet() { | ||||
| 	struct packetlist * new_item = NULL; | ||||
| 	new_item = m_malloc(sizeof(struct packetlist)); | ||||
| 	new_item->next = NULL; | ||||
| 	 | ||||
| 	new_item->payload = buf_newcopy(ses.writepayload); | ||||
| 	buf_setpos(ses.writepayload, 0); | ||||
| 	buf_setlen(ses.writepayload, 0); | ||||
| 	 | ||||
| 	if (ses.reply_queue_tail) { | ||||
| 		ses.reply_queue_tail->next = new_item; | ||||
| 	} else { | ||||
| 		ses.reply_queue_head = new_item; | ||||
| 		ses.reply_queue_tail = new_item; | ||||
| 	} | ||||
| 	TRACE(("leave enqueue_reply_packet")) | ||||
| } | ||||
| 
 | ||||
| void maybe_flush_reply_queue() { | ||||
| 	struct packetlist *tmp_item = NULL, *curr_item = NULL; | ||||
| 	if (!ses.dataallowed) | ||||
| 	{ | ||||
| 		TRACE(("maybe_empty_reply_queue - no data allowed")) | ||||
| 		return; | ||||
| 	} | ||||
| 		 | ||||
| 	for (curr_item = ses.reply_queue_head; curr_item; ) { | ||||
| 		CHECKCLEARTOWRITE(); | ||||
| 		buf_putbytes(ses.writepayload, | ||||
| 			curr_item->payload->data, curr_item->payload->len); | ||||
| 			 | ||||
| 		buf_free(curr_item->payload); | ||||
| 		tmp_item = curr_item; | ||||
| 		curr_item = curr_item->next; | ||||
| 		m_free(tmp_item); | ||||
| 		encrypt_packet(); | ||||
| 	} | ||||
| 	ses.reply_queue_head = ses.reply_queue_tail = NULL; | ||||
| } | ||||
| 	 | ||||
| /* encrypt the writepayload, putting into writebuf, ready for write_packet()
 | ||||
|  * to put on the wire */ | ||||
| @ -413,9 +466,20 @@ void encrypt_packet() { | ||||
| 	unsigned char blocksize, macsize; | ||||
| 	buffer * writebuf; /* the packet which will go on the wire */ | ||||
| 	buffer * clearwritebuf; /* unencrypted, possibly compressed */ | ||||
| 	unsigned char type; | ||||
| 	 | ||||
| 	type = ses.writepayload->data[0]; | ||||
| 	TRACE(("enter encrypt_packet()")) | ||||
| 	TRACE(("encrypt_packet type is %d", ses.writepayload->data[0])) | ||||
| 	TRACE(("encrypt_packet type is %d", type)) | ||||
| 	 | ||||
| 	if (!ses.dataallowed && !packet_is_okay_kex(type)) { | ||||
| 		/* During key exchange only particular packets are allowed.
 | ||||
| 			Since this type isn't OK we just enqueue it to send  | ||||
| 			after the KEX, see maybe_flush_reply_queue */ | ||||
| 		enqueue_reply_packet(); | ||||
| 		return; | ||||
| 	} | ||||
| 		 | ||||
| 	blocksize = ses.keys->trans_algo_crypt->blocksize; | ||||
| 	macsize = ses.keys->trans_algo_mac->hashsize; | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										1
									
								
								packet.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								packet.h
									
									
									
									
									
								
							| @ -35,6 +35,7 @@ void encrypt_packet(); | ||||
| 
 | ||||
| void process_packet(); | ||||
| 
 | ||||
| void maybe_flush_reply_queue(); | ||||
| typedef struct PacketType { | ||||
| 	unsigned char type; /* SSH_MSG_FOO */ | ||||
| 	void (*handler)(); | ||||
|  | ||||
							
								
								
									
										10
									
								
								session.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								session.h
									
									
									
									
									
								
							| @ -81,6 +81,12 @@ struct key_context { | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| struct packetlist; | ||||
| struct packetlist { | ||||
| 	struct packetlist *next; | ||||
| 	buffer * payload; | ||||
| }; | ||||
| 
 | ||||
| struct sshsession { | ||||
| 
 | ||||
| 	/* Is it a client or server? */ | ||||
| @ -138,6 +144,10 @@ struct sshsession { | ||||
| 	buffer* transkexinit; /* the kexinit packet we send should be kept so we
 | ||||
| 							 can add it to the hash when generating keys */ | ||||
| 							 | ||||
| 	/* a list of queued replies that should be sent after a KEX has
 | ||||
| 	   concluded (ie, while dataallowed was unset)*/ | ||||
| 	struct packetlist *reply_queue_head, *reply_queue_tail; | ||||
| 
 | ||||
| 	algo_type*(*buf_match_algo)(buffer*buf, algo_type localalgos[], | ||||
| 			int *goodguess); /* The function to use to choose which algorithm
 | ||||
| 								to use from the ones presented by the remote | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user