mirror of
				https://github.com/clearml/dropbear
				synced 2025-06-26 18:17:32 +00:00 
			
		
		
		
	New standard linked list to use, rather than adhoc SignKeyList or TCPFwdList
--HG-- branch : agent-client extra : convert_revision : 5465e639cc3f5ee0c6c55f0de6e7b6d5a8769da3
This commit is contained in:
		
							parent
							
								
									9dc9aff016
								
							
						
					
					
						commit
						c742137dc8
					
				| @ -20,7 +20,7 @@ COMMONOBJS=dbutil.o buffer.o \ | ||||
| 		dss.o bignum.o \
 | ||||
| 		signkey.o rsa.o random.o \
 | ||||
| 		queue.o \
 | ||||
| 		atomicio.o compat.o  fake-rfc2553.o | ||||
| 		atomicio.o compat.o  fake-rfc2553.o  | ||||
| 
 | ||||
| SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \
 | ||||
| 		svr-authpasswd.o svr-authpubkey.o svr-authpubkeyoptions.o svr-session.o svr-service.o \
 | ||||
| @ -30,7 +30,7 @@ SVROBJS=svr-kex.o svr-algo.o svr-auth.o sshpty.o \ | ||||
| CLIOBJS=cli-algo.o cli-main.o cli-auth.o cli-authpasswd.o cli-kex.o \
 | ||||
| 		cli-session.o cli-service.o cli-runopts.o cli-chansession.o \
 | ||||
| 		cli-authpubkey.o cli-tcpfwd.o cli-channel.o cli-authinteract.o \
 | ||||
| 		cli-agentfwd.o | ||||
| 		cli-agentfwd.o list.o | ||||
| 
 | ||||
| CLISVROBJS=common-session.o packet.o common-algo.o common-kex.o \
 | ||||
| 			common-channel.o common-chansession.o termcodes.o loginrec.o \
 | ||||
|  | ||||
| @ -28,6 +28,7 @@ | ||||
| #include "chansession.h" | ||||
| #include "channel.h" | ||||
| #include "auth.h" | ||||
| #include "list.h" | ||||
| 
 | ||||
| /* An agent reply can be reasonably large, as it can
 | ||||
|  * contain a list of all public keys held by the agent. | ||||
| @ -35,11 +36,13 @@ | ||||
| #define MAX_AGENT_REPLY  10000 | ||||
| 
 | ||||
| int agentreq(struct ChanSess * chansess); | ||||
| void agentsetauth(struct ChanSess *chansess); | ||||
| void agentcleanup(struct ChanSess * chansess); | ||||
| void agentset(struct ChanSess *chansess); | ||||
| 
 | ||||
| void load_agent_keys(struct SignKeyList * ret_list); | ||||
| /* client functions */ | ||||
| void load_agent_keys(m_list * ret_list); | ||||
| void agent_buf_sign(buffer *sigblob, sign_key *key,  | ||||
|     const unsigned char *data, unsigned int len); | ||||
| 
 | ||||
| #ifdef __hpux | ||||
| #define seteuid(a)       setresuid(-1, (a), -1) | ||||
|  | ||||
							
								
								
									
										20
									
								
								auth.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								auth.h
									
									
									
									
									
								
							| @ -124,26 +124,6 @@ struct AuthState { | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| /* Sources for signing keys */ | ||||
| typedef enum { | ||||
| 	SIGNKEY_SOURCE_RAW_FILE, | ||||
| 	SIGNKEY_SOURCE_AGENT, | ||||
| } signkey_source; | ||||
| 
 | ||||
| struct SignKeyList; | ||||
| /* A singly linked list of signing keys */ | ||||
| struct SignKeyList { | ||||
| 
 | ||||
| 	sign_key *key; | ||||
| 	int type; /* The type of key */ | ||||
| 	struct SignKeyList *next; | ||||
| 	signkey_source source; | ||||
| 	char *filename; | ||||
| 	/* the buffer? for encrypted keys, so we can later get
 | ||||
| 	 * the private key portion */ | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| #ifdef ENABLE_SVR_PUBKEY_OPTIONS | ||||
| struct PubKeyOptions; | ||||
| struct PubKeyOptions { | ||||
|  | ||||
							
								
								
									
										14
									
								
								buffer.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								buffer.c
									
									
									
									
									
								
							| @ -223,6 +223,20 @@ unsigned char* buf_getstring(buffer* buf, unsigned int *retlen) { | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* Return a string as a newly allocated buffer */ | ||||
| buffer * buf_getstringbuf(buffer *buf) { | ||||
| 	buffer *ret; | ||||
| 	unsigned char* str; | ||||
| 	unsigned int len; | ||||
| 	str = buf_getstring(buf, &len); | ||||
| 	ret = m_malloc(sizeof(*ret)); | ||||
| 	ret->data = str; | ||||
| 	ret->len = len; | ||||
| 	ret->size = len; | ||||
| 	ret->pos = 0; | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* Just increment the buffer position the same as if we'd used buf_getstring,
 | ||||
|  * but don't bother copying/malloc()ing for it */ | ||||
| void buf_eatstring(buffer *buf) { | ||||
|  | ||||
							
								
								
									
										1
									
								
								buffer.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								buffer.h
									
									
									
									
									
								
							| @ -55,6 +55,7 @@ void buf_putbyte(buffer* buf, unsigned char val); | ||||
| unsigned char* buf_getptr(buffer* buf, unsigned int len); | ||||
| unsigned char* buf_getwriteptr(buffer* buf, unsigned int len); | ||||
| unsigned char* buf_getstring(buffer* buf, unsigned int *retlen); | ||||
| buffer * buf_getstringbuf(buffer *buf); | ||||
| void buf_eatstring(buffer *buf); | ||||
| void buf_putint(buffer* buf, unsigned int val); | ||||
| void buf_putstring(buffer* buf, const unsigned char* str, unsigned int len); | ||||
|  | ||||
| @ -22,10 +22,6 @@ | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||
|  * SOFTWARE. */ | ||||
| 
 | ||||
| /* The basic protocol use to communicate with the agent is defined in
 | ||||
|  * draft-ylonen-ssh-protocol-00.txt, with the ssh2 extensions defined through | ||||
|  * openssh's implementation. */ | ||||
| 
 | ||||
| #include "includes.h" | ||||
| 
 | ||||
| #ifdef ENABLE_CLI_AGENTFWD | ||||
| @ -45,6 +41,9 @@ | ||||
| #include "signkey.h" | ||||
| #include "auth.h" | ||||
| 
 | ||||
| /* The protocol implemented to talk to OpenSSH's SSH2 agent is documented in
 | ||||
|    PROTOCOL.agent in recent OpenSSH source distributions (5.1p1 has it). */ | ||||
| 
 | ||||
| static int new_agent_chan(struct Channel * channel); | ||||
| 
 | ||||
| const struct ChanType cli_chan_agent = { | ||||
| @ -161,13 +160,12 @@ out: | ||||
| 	return inbuf; | ||||
| } | ||||
| 
 | ||||
| static void agent_get_key_list(int fd, struct SignKeyList * ret_list) | ||||
| static void agent_get_key_list(int fd, m_list * ret_list) | ||||
| { | ||||
| 	buffer * inbuf = NULL; | ||||
| 	unsigned int num = 0; | ||||
| 	unsigned char packet_type; | ||||
| 	unsigned int i; | ||||
| 	struct SignKeyList *key = NULL; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES); | ||||
| @ -177,14 +175,11 @@ static void agent_get_key_list(int fd, struct SignKeyList * ret_list) | ||||
| 	} | ||||
| 
 | ||||
| 	/* The reply has a format of:
 | ||||
| 	 * byte     packet_type | ||||
| 	 * int      num_keys | ||||
| 	 * | ||||
| 	 * string    keyblob1 | ||||
| 	 * string    comment1 | ||||
| 	 * ... | ||||
| 	 * string    keyblob(n) | ||||
| 	 * string    comment(n) | ||||
| 		byte			SSH2_AGENT_IDENTITIES_ANSWER | ||||
| 		uint32			num_keys | ||||
|   	   Followed by zero or more consecutive keys, encoded as: | ||||
|        	 string			key_blob | ||||
|     	 string			key_comment | ||||
| 	 */ | ||||
| 	packet_type = buf_getbyte(inbuf); | ||||
| 	if (packet_type != SSH2_AGENT_IDENTITIES_ANSWER) { | ||||
| @ -195,25 +190,24 @@ static void agent_get_key_list(int fd, struct SignKeyList * ret_list) | ||||
| 	for (i = 0; i < num; i++) { | ||||
| 		sign_key * pubkey = NULL; | ||||
| 		int key_type = DROPBEAR_SIGNKEY_ANY; | ||||
| 		buffer * key_buf; | ||||
| 		struct SignKeyList *nextkey = NULL; | ||||
| 
 | ||||
| 		nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList)); | ||||
| 		ret_list->next = nextkey; | ||||
| 		ret_list = nextkey; | ||||
| 
 | ||||
| 		/* each public key is encoded as a string */ | ||||
| 		key_buf = buf_getstringbuf(inbuf); | ||||
| 		pubkey = new_sign_key(); | ||||
| 		ret = buf_get_pub_key(inbuf, pubkey, &key_type); | ||||
| 		ret = buf_get_pub_key(key_buf, pubkey, &key_type); | ||||
| 		buf_free(key_buf); | ||||
| 		if (ret != DROPBEAR_SUCCESS) { | ||||
| 			/* This is slack, properly would cleanup vars etc */ | ||||
| 			dropbear_exit("Bad pubkey received from agent"); | ||||
| 		} | ||||
| 		pubkey->type = key_type; | ||||
| 		pubkey->source = SIGNKEY_SOURCE_AGENT; | ||||
| 
 | ||||
| 		key->key = pubkey; | ||||
| 		key->next = NULL; | ||||
| 		key->type = key_type; | ||||
| 		key->source = SIGNKEY_SOURCE_AGENT; | ||||
| 		list_append(ret_list, pubkey); | ||||
| 
 | ||||
| 		/* We'll ignore the comment */ | ||||
| 		/* We'll ignore the comment for now. might want it later.*/ | ||||
| 		buf_eatstring(inbuf); | ||||
| 	} | ||||
| 
 | ||||
| @ -224,8 +218,9 @@ out: | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Returned keys are appended to ret_list */ | ||||
| void load_agent_keys(struct SignKeyList * ret_list) | ||||
| /* Returned keys are prepended to ret_list, which will
 | ||||
|    be updated. */ | ||||
| void load_agent_keys(m_list *ret_list) | ||||
| { | ||||
| 	int fd; | ||||
| 	fd = connect_agent(); | ||||
| @ -237,13 +232,9 @@ void load_agent_keys(struct SignKeyList * ret_list) | ||||
| 	agent_get_key_list(fd, ret_list); | ||||
| 	close(fd); | ||||
| } | ||||
| 	 | ||||
| // general procedure:
 | ||||
| // - get the list of keys from the agent
 | ||||
| // - foreach, send a dummy userauth_pubkey message to the server and see
 | ||||
| // if it lets us in
 | ||||
| // - if it does, sign and auth
 | ||||
| // - if not, repeat.
 | ||||
| //
 | ||||
| 
 | ||||
| void agent_buf_sign(buffer *sigblob, sign_key *key,  | ||||
| 		const unsigned char *data, unsigned int len) { | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -30,6 +30,7 @@ | ||||
| #include "ssh.h" | ||||
| #include "runopts.h" | ||||
| #include "auth.h" | ||||
| #include "agentfwd.h" | ||||
| 
 | ||||
| #ifdef ENABLE_CLI_PUBKEY_AUTH | ||||
| static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign); | ||||
| @ -37,31 +38,23 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign); | ||||
| /* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request.
 | ||||
|  * We use it to remove the key we tried from the list */ | ||||
| void cli_pubkeyfail() { | ||||
| 
 | ||||
| 	struct SignKeyList *keyitem; | ||||
| 	struct SignKeyList **previtem; | ||||
| 
 | ||||
| 	TRACE(("enter cli_pubkeyfail")) | ||||
| 	previtem = &cli_opts.privkeys; | ||||
| 
 | ||||
| 	/* Find the key we failed with, and remove it */ | ||||
| 	for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) { | ||||
| 		if (keyitem == cli_ses.lastprivkey) { | ||||
| 			*previtem = keyitem->next; | ||||
| 	m_list_elem *iter; | ||||
| 	for (iter = cli_opts.privkeys->first; iter; iter = iter->next) { | ||||
| 		sign_key *iter_key = (sign_key*)iter->item; | ||||
| 		 | ||||
| 		if (iter_key == cli_ses.lastprivkey) | ||||
| 		{ | ||||
| 			/* found the failing key */ | ||||
| 			list_remove(iter); | ||||
| 			sign_key_free(iter_key); | ||||
| 			cli_ses.lastprivkey = NULL; | ||||
| 			return; | ||||
| 		} | ||||
| 		previtem = &keyitem; | ||||
| 	} | ||||
| 
 | ||||
| 	sign_key_free(cli_ses.lastprivkey->key); /* It won't be used again */ | ||||
| 	m_free(cli_ses.lastprivkey->filename); | ||||
| 	m_free(cli_ses.lastprivkey); | ||||
| 
 | ||||
| 	TRACE(("leave cli_pubkeyfail")) | ||||
| } | ||||
| 
 | ||||
| void recv_msg_userauth_pk_ok() { | ||||
| 
 | ||||
| 	struct SignKeyList *keyitem = NULL; | ||||
| 	m_list_elem *iter; | ||||
| 	buffer* keybuf = NULL; | ||||
| 	char* algotype = NULL; | ||||
| 	unsigned int algolen; | ||||
| @ -81,9 +74,9 @@ void recv_msg_userauth_pk_ok() { | ||||
| 
 | ||||
| 	/* Iterate through our keys, find which one it was that matched, and
 | ||||
| 	 * send a real request with that key */ | ||||
| 	for (keyitem = cli_opts.privkeys; keyitem != NULL; keyitem = keyitem->next) { | ||||
| 
 | ||||
| 		if (keyitem->type != keytype) { | ||||
| 	for (iter = cli_opts.privkeys->first; iter; iter = iter->next) { | ||||
| 		sign_key *key = (sign_key*)iter->item; | ||||
| 		if (key->type != keytype) { | ||||
| 			/* Types differed */ | ||||
| 			TRACE(("types differed")) | ||||
| 			continue; | ||||
| @ -91,7 +84,7 @@ void recv_msg_userauth_pk_ok() { | ||||
| 
 | ||||
| 		/* Now we compare the contents of the key */ | ||||
| 		keybuf->pos = keybuf->len = 0; | ||||
| 		buf_put_pub_key(keybuf, keyitem->key, keytype); | ||||
| 		buf_put_pub_key(keybuf, key, keytype); | ||||
| 		buf_setpos(keybuf, 0); | ||||
| 		buf_incrpos(keybuf, 4); /* first int is the length of the remainder (ie
 | ||||
| 								   remotelen) which has already been taken from | ||||
| @ -115,11 +108,11 @@ void recv_msg_userauth_pk_ok() { | ||||
| 	} | ||||
| 	buf_free(keybuf); | ||||
| 
 | ||||
| 	if (keyitem != NULL) { | ||||
| 	if (iter != NULL) { | ||||
| 		TRACE(("matching key")) | ||||
| 		/* XXX TODO: if it's an encrypted key, here we ask for their
 | ||||
| 		 * password */ | ||||
| 		send_msg_userauth_pubkey(keyitem->key, keytype, 1); | ||||
| 		send_msg_userauth_pubkey((sign_key*)iter->item, keytype, 1); | ||||
| 	} else { | ||||
| 		TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part")) | ||||
| 	} | ||||
| @ -127,6 +120,25 @@ void recv_msg_userauth_pk_ok() { | ||||
| 	TRACE(("leave recv_msg_userauth_pk_ok")) | ||||
| } | ||||
| 
 | ||||
| void cli_buf_put_sign(buffer* buf, sign_key *key, int type,  | ||||
| 			const unsigned char *data, unsigned int len) | ||||
| { | ||||
| 	if (key->source == SIGNKEY_SOURCE_AGENT) { | ||||
| 		/* Format the agent signature ourselves, as buf_put_sign would. */ | ||||
| 		buffer *sigblob; | ||||
| 		sigblob = buf_new(MAX_PUBKEY_SIZE); | ||||
| 		agent_buf_sign(sigblob, key, data, len); | ||||
| 		buf_setpos(sigblob, 0); | ||||
| 		buf_putstring(buf, buf_getptr(sigblob, sigblob->len), | ||||
| 				sigblob->len); | ||||
| 
 | ||||
| 		buf_free(sigblob); | ||||
| 	} else { | ||||
| 		buf_put_sign(buf, key, type, data, len); | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
| 
 | ||||
| /* TODO: make it take an agent reference to use as well */ | ||||
| static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) { | ||||
| 
 | ||||
| @ -170,6 +182,7 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) { | ||||
| 	TRACE(("leave send_msg_userauth_pubkey")) | ||||
| } | ||||
| 
 | ||||
| /* Returns 1 if a key was tried */ | ||||
| int cli_auth_pubkey() { | ||||
| 
 | ||||
| 	TRACE(("enter cli_auth_pubkey")) | ||||
| @ -177,15 +190,15 @@ int cli_auth_pubkey() { | ||||
| 	if (cli_opts.agent_fwd && | ||||
| 			!cli_opts.agent_keys_loaded) { | ||||
| 		/* get the list of available keys from the agent */ | ||||
| 		load_agent_keys(&cli_opts.privkeys); | ||||
| 		load_agent_keys(cli_opts.privkeys); | ||||
| 		cli_opts.agent_keys_loaded = 1; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cli_opts.privkeys != NULL) { | ||||
| 	if (cli_opts.privkeys->first) { | ||||
| 		sign_key * key = (sign_key*)cli_opts.privkeys->first->item; | ||||
| 		/* Send a trial request */ | ||||
| 		send_msg_userauth_pubkey(cli_opts.privkeys->key, | ||||
| 				cli_opts.privkeys->type, 0); | ||||
| 		cli_ses.lastprivkey = cli_opts.privkeys; | ||||
| 		send_msg_userauth_pubkey(key, key->type, 0); | ||||
| 		cli_ses.lastprivkey = key; | ||||
| 		TRACE(("leave cli_auth_pubkey-success")) | ||||
| 		return 1; | ||||
| 	} else { | ||||
|  | ||||
| @ -424,16 +424,3 @@ void cli_send_chansess_request() { | ||||
| 	TRACE(("leave cli_send_chansess_request")) | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #if 0 | ||||
| 	while (cli_opts.localfwds != NULL) { | ||||
| 		ret = cli_localtcp(cli_opts.localfwds->listenport, | ||||
| 				cli_opts.localfwds->connectaddr, | ||||
| 				cli_opts.localfwds->connectport); | ||||
| 		if (ret == DROPBEAR_FAILURE) { | ||||
| 			dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", | ||||
| 					cli_opts.localfwds->listenport, | ||||
| 					cli_opts.localfwds->connectaddr, | ||||
| 					cli_opts.localfwds->connectport); | ||||
| #endif | ||||
|  | ||||
| @ -29,6 +29,7 @@ | ||||
| #include "dbutil.h" | ||||
| #include "algo.h" | ||||
| #include "tcpfwd.h" | ||||
| #include "list.h" | ||||
| 
 | ||||
| cli_runopts cli_opts; /* GLOBAL */ | ||||
| 
 | ||||
| @ -40,7 +41,7 @@ static void fill_own_user(); | ||||
| static void loadidentityfile(const char* filename); | ||||
| #endif | ||||
| #ifdef ENABLE_CLI_ANYTCPFWD | ||||
| static void addforward(const char* str, struct TCPFwdList** fwdlist); | ||||
| static void addforward(const char* str, m_list *fwdlist); | ||||
| #endif | ||||
| #ifdef ENABLE_CLI_NETCAT | ||||
| static void add_netcat(const char *str); | ||||
| @ -128,14 +129,14 @@ void cli_getopts(int argc, char ** argv) { | ||||
| 	cli_opts.always_accept_key = 0; | ||||
| 	cli_opts.is_subsystem = 0; | ||||
| #ifdef ENABLE_CLI_PUBKEY_AUTH | ||||
| 	cli_opts.privkeys = NULL; | ||||
| 	cli_opts.privkeys = list_new(); | ||||
| #endif | ||||
| #ifdef ENABLE_CLI_LOCALTCPFWD | ||||
| 	cli_opts.localfwds = NULL; | ||||
| 	cli_opts.localfwds = list_new(); | ||||
| 	opts.listen_fwd_all = 0; | ||||
| #endif | ||||
| #ifdef ENABLE_CLI_REMOTETCPFWD | ||||
| 	cli_opts.remotefwds = NULL; | ||||
| 	cli_opts.remotefwds = list_new(); | ||||
| #endif | ||||
| #ifdef ENABLE_CLI_AGENTFWD | ||||
| 	cli_opts.agent_fwd = 0; | ||||
| @ -165,7 +166,7 @@ void cli_getopts(int argc, char ** argv) { | ||||
| #ifdef ENABLE_CLI_REMOTETCPFWD | ||||
| 		if (nextisremote) { | ||||
| 			TRACE(("nextisremote true")) | ||||
| 			addforward(argv[i], &cli_opts.remotefwds); | ||||
| 			addforward(argv[i], cli_opts.remotefwds); | ||||
| 			nextisremote = 0; | ||||
| 			continue; | ||||
| 		} | ||||
| @ -173,7 +174,7 @@ void cli_getopts(int argc, char ** argv) { | ||||
| #ifdef ENABLE_CLI_LOCALTCPFWD | ||||
| 		if (nextislocal) { | ||||
| 			TRACE(("nextislocal true")) | ||||
| 			addforward(argv[i], &cli_opts.localfwds); | ||||
| 			addforward(argv[i], cli_opts.localfwds); | ||||
| 			nextislocal = 0; | ||||
| 			continue; | ||||
| 		} | ||||
| @ -406,8 +407,6 @@ void cli_getopts(int argc, char ** argv) { | ||||
| 
 | ||||
| #ifdef ENABLE_CLI_PUBKEY_AUTH | ||||
| static void loadidentityfile(const char* filename) { | ||||
| 
 | ||||
| 	struct SignKeyList * nextkey; | ||||
| 	sign_key *key; | ||||
| 	int keytype; | ||||
| 
 | ||||
| @ -417,13 +416,10 @@ static void loadidentityfile(const char* filename) { | ||||
| 		fprintf(stderr, "Failed loading keyfile '%s'\n", filename); | ||||
| 		sign_key_free(key); | ||||
| 	} else { | ||||
| 		nextkey = (struct SignKeyList*)m_malloc(sizeof(struct SignKeyList)); | ||||
| 		nextkey->key = key; | ||||
| 		nextkey->filename = m_strdup(filename); | ||||
| 		nextkey->next = cli_opts.privkeys; | ||||
| 		nextkey->type = keytype; | ||||
| 		nextkey->source = SIGNKEY_SOURCE_RAW_FILE; | ||||
| 		cli_opts.privkeys = nextkey; | ||||
| 		key->type = keytype; | ||||
| 		key->source = SIGNKEY_SOURCE_RAW_FILE; | ||||
| 		key->filename = m_strdup(filename); | ||||
| 		list_append(cli_opts.privkeys, key); | ||||
| 	} | ||||
| } | ||||
| #endif | ||||
| @ -435,12 +431,13 @@ multihop_passthrough_args() { | ||||
| 	char *ret; | ||||
| 	int total; | ||||
| 	unsigned int len = 0; | ||||
| 	struct SignKeyList *nextkey; | ||||
| 	m_list_elem *iter; | ||||
| 	/* Fill out -i and -W options that make sense for all
 | ||||
| 	 * the intermediate processes */ | ||||
| 	for (nextkey = cli_opts.privkeys; nextkey; nextkey = nextkey->next) | ||||
| 	for (iter = cli_opts.privkeys->first; iter; iter = iter->next) | ||||
| 	{ | ||||
| 		len += 3 + strlen(nextkey->filename); | ||||
| 		sign_key * key = (sign_key*)iter->item; | ||||
| 		len += 3 + strlen(key->filename); | ||||
| 	} | ||||
| 	len += 20; // space for -W <size>, terminator.
 | ||||
| 	ret = m_malloc(len); | ||||
| @ -452,10 +449,11 @@ multihop_passthrough_args() { | ||||
| 		total += written; | ||||
| 	} | ||||
| 
 | ||||
| 	for (nextkey = cli_opts.privkeys; nextkey; nextkey = nextkey->next) | ||||
| 	for (iter = cli_opts.privkeys->first; iter; iter = iter->next) | ||||
| 	{ | ||||
| 		sign_key * key = (sign_key*)iter->item; | ||||
| 		const size_t size = len - total; | ||||
| 		int written = snprintf(ret+total, size, "-i %s", nextkey->filename); | ||||
| 		int written = snprintf(ret+total, size, "-i %s", key->filename); | ||||
| 		dropbear_assert(written < size); | ||||
| 		total += written; | ||||
| 	} | ||||
| @ -621,12 +619,12 @@ static void fill_own_user() { | ||||
| #ifdef ENABLE_CLI_ANYTCPFWD | ||||
| /* Turn a "listenport:remoteaddr:remoteport" string into into a forwarding
 | ||||
|  * set, and add it to the forwarding list */ | ||||
| static void addforward(const char* origstr, struct TCPFwdList** fwdlist) { | ||||
| static void addforward(const char* origstr, m_list *fwdlist) { | ||||
| 
 | ||||
| 	char * listenport = NULL; | ||||
| 	char * connectport = NULL; | ||||
| 	char * connectaddr = NULL; | ||||
| 	struct TCPFwdList* newfwd = NULL; | ||||
| 	struct TCPFwdEntry* newfwd = NULL; | ||||
| 	char * str = NULL; | ||||
| 
 | ||||
| 	TRACE(("enter addforward")) | ||||
| @ -653,7 +651,7 @@ static void addforward(const char* origstr, struct TCPFwdList** fwdlist) { | ||||
| 	*connectport = '\0'; | ||||
| 	connectport++; | ||||
| 
 | ||||
| 	newfwd = (struct TCPFwdList*)m_malloc(sizeof(struct TCPFwdList)); | ||||
| 	newfwd = m_malloc(sizeof(struct TCPFwdEntry)); | ||||
| 
 | ||||
| 	/* Now we check the ports - note that the port ints are unsigned,
 | ||||
| 	 * the check later only checks for >= MAX_PORT */ | ||||
| @ -680,8 +678,7 @@ static void addforward(const char* origstr, struct TCPFwdList** fwdlist) { | ||||
| 	} | ||||
| 
 | ||||
| 	newfwd->have_reply = 0; | ||||
| 	newfwd->next = *fwdlist; | ||||
| 	*fwdlist = newfwd; | ||||
| 	list_append(fwdlist, newfwd); | ||||
| 
 | ||||
| 	TRACE(("leave addforward: done")) | ||||
| 	return; | ||||
|  | ||||
							
								
								
									
										84
									
								
								cli-tcpfwd.c
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								cli-tcpfwd.c
									
									
									
									
									
								
							| @ -59,27 +59,22 @@ static const struct ChanType cli_chan_tcplocal = { | ||||
| 
 | ||||
| #ifdef ENABLE_CLI_LOCALTCPFWD | ||||
| void setup_localtcp() { | ||||
| 
 | ||||
| 	m_list_elem *iter; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	TRACE(("enter setup_localtcp")) | ||||
| 
 | ||||
| 	if (cli_opts.localfwds == NULL) { | ||||
| 		TRACE(("cli_opts.localfwds == NULL")) | ||||
| 	} | ||||
| 
 | ||||
| 	while (cli_opts.localfwds != NULL) { | ||||
| 		ret = cli_localtcp(cli_opts.localfwds->listenport, | ||||
| 				cli_opts.localfwds->connectaddr, | ||||
| 				cli_opts.localfwds->connectport); | ||||
| 	for (iter = cli_opts.localfwds->first; iter; iter = iter->next) { | ||||
| 		struct TCPFwdEntry * fwd = (struct TCPFwdEntry*)iter->item; | ||||
| 		ret = cli_localtcp(fwd->listenport, | ||||
| 				fwd->connectaddr, | ||||
| 				fwd->connectport); | ||||
| 		if (ret == DROPBEAR_FAILURE) { | ||||
| 			dropbear_log(LOG_WARNING, "Failed local port forward %d:%s:%d", | ||||
| 					cli_opts.localfwds->listenport, | ||||
| 					cli_opts.localfwds->connectaddr, | ||||
| 					cli_opts.localfwds->connectport); | ||||
| 		} | ||||
| 
 | ||||
| 		cli_opts.localfwds = cli_opts.localfwds->next; | ||||
| 					fwd->listenport, | ||||
| 					fwd->connectaddr, | ||||
| 					fwd->connectport); | ||||
| 		}		 | ||||
| 	} | ||||
| 	TRACE(("leave setup_localtcp")) | ||||
| 
 | ||||
| @ -148,60 +143,47 @@ static void send_msg_global_request_remotetcp(int port) { | ||||
|  * being in the same order as we sent the requests. This is the ordering | ||||
|  * of the cli_opts.remotefwds list */ | ||||
| void cli_recv_msg_request_success() { | ||||
| 
 | ||||
| 	/* Nothing in the packet. We just mark off that we have received the reply,
 | ||||
| 	 * so that we can report failure for later ones. */ | ||||
| 	struct TCPFwdList * iter = NULL; | ||||
| 
 | ||||
| 	iter = cli_opts.remotefwds; | ||||
| 	while (iter != NULL) { | ||||
| 		if (!iter->have_reply) | ||||
| 		{ | ||||
| 			iter->have_reply = 1; | ||||
| 	m_list_elem * iter = NULL; | ||||
| 	for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { | ||||
| 		struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item; | ||||
| 		if (!fwd->have_reply) { | ||||
| 			fwd->have_reply = 1; | ||||
| 			return; | ||||
| 		} | ||||
| 		iter = iter->next; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void cli_recv_msg_request_failure() { | ||||
| 	struct TCPFwdList * iter = NULL; | ||||
| 
 | ||||
| 	iter = cli_opts.remotefwds; | ||||
| 	while (iter != NULL) { | ||||
| 		if (!iter->have_reply) | ||||
| 		{ | ||||
| 			iter->have_reply = 1; | ||||
| 			dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", iter->listenport, iter->connectaddr, iter->connectport); | ||||
| 	m_list_elem *iter; | ||||
| 	for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { | ||||
| 		struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item; | ||||
| 		if (!fwd->have_reply) { | ||||
| 			fwd->have_reply = 1; | ||||
| 			dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", fwd->listenport, fwd->connectaddr, fwd->connectport); | ||||
| 			return; | ||||
| 		} | ||||
| 		iter = iter->next; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void setup_remotetcp() { | ||||
| 
 | ||||
| 	struct TCPFwdList * iter = NULL; | ||||
| 
 | ||||
| 	m_list_elem *iter; | ||||
| 	TRACE(("enter setup_remotetcp")) | ||||
| 
 | ||||
| 	if (cli_opts.remotefwds == NULL) { | ||||
| 		TRACE(("cli_opts.remotefwds == NULL")) | ||||
| 	for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { | ||||
| 		struct TCPFwdEntry *fwd = (struct TCPFwdEntry*)iter->item; | ||||
| 		send_msg_global_request_remotetcp(fwd->listenport); | ||||
| 	} | ||||
| 
 | ||||
| 	iter = cli_opts.remotefwds; | ||||
| 
 | ||||
| 	while (iter != NULL) { | ||||
| 		send_msg_global_request_remotetcp(iter->listenport); | ||||
| 		iter = iter->next; | ||||
| 	} | ||||
| 	TRACE(("leave setup_remotetcp")) | ||||
| } | ||||
| 
 | ||||
| static int newtcpforwarded(struct Channel * channel) { | ||||
| 
 | ||||
| 	unsigned int origport; | ||||
| 	struct TCPFwdList * iter = NULL; | ||||
| 	m_list_elem * iter = NULL; | ||||
| 	struct TCPFwdEntry *fwd; | ||||
| 	char portstring[NI_MAXSERV]; | ||||
| 	int sock; | ||||
| 	int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED; | ||||
| @ -212,13 +194,11 @@ static int newtcpforwarded(struct Channel * channel) { | ||||
| 	origport = buf_getint(ses.payload); | ||||
| 
 | ||||
| 	/* Find which port corresponds */ | ||||
| 	iter = cli_opts.remotefwds; | ||||
| 
 | ||||
| 	while (iter != NULL) { | ||||
| 		if (origport == iter->listenport) { | ||||
| 	for (iter = cli_opts.remotefwds->first; iter; iter = iter->next) { | ||||
| 		fwd = (struct TCPFwdEntry*)iter->item; | ||||
| 		if (origport == fwd->listenport) { | ||||
| 			break; | ||||
| 		} | ||||
| 		iter = iter->next; | ||||
| 	} | ||||
| 
 | ||||
| 	if (iter == NULL) { | ||||
| @ -228,8 +208,8 @@ static int newtcpforwarded(struct Channel * channel) { | ||||
| 		goto out; | ||||
| 	} | ||||
| 	 | ||||
| 	snprintf(portstring, sizeof(portstring), "%d", iter->connectport); | ||||
| 	sock = connect_remote(iter->connectaddr, portstring, 1, NULL); | ||||
| 	snprintf(portstring, sizeof(portstring), "%d", fwd->connectport); | ||||
| 	sock = connect_remote(fwd->connectaddr, portstring, 1, NULL); | ||||
| 	if (sock < 0) { | ||||
| 		TRACE(("leave newtcpdirect: sock failed")) | ||||
| 		err = SSH_OPEN_CONNECT_FAILED; | ||||
|  | ||||
							
								
								
									
										49
									
								
								list.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								list.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,49 @@ | ||||
| #include "options.h" | ||||
| #include "dbutil.h" | ||||
| #include "list.h" | ||||
| 
 | ||||
| void list_append(m_list *list, void *item) { | ||||
| 	m_list_elem *elem; | ||||
| 	 | ||||
| 	elem = m_malloc(sizeof(*elem)); | ||||
| 	elem->item = item; | ||||
| 	elem->list = list; | ||||
| 	elem->next = NULL; | ||||
| 	if (!list->first) { | ||||
| 		list->first = elem; | ||||
| 		elem->prev = NULL; | ||||
| 	} else { | ||||
| 		elem->prev = list->last; | ||||
| 		list->last->next = elem; | ||||
| 	} | ||||
| 	list->last = elem; | ||||
| } | ||||
| 
 | ||||
| m_list * list_new() { | ||||
| 	m_list *ret = m_malloc(sizeof(m_list)); | ||||
| 	ret->first = ret->last = NULL; | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| void * list_remove(m_list_elem *elem) { | ||||
| 	void *item = elem->item; | ||||
| 	m_list *list = elem->list; | ||||
| 	if (list->first == elem) | ||||
| 	{ | ||||
| 		list->first = elem->next; | ||||
| 	} | ||||
| 	if (list->last == elem) | ||||
| 	{ | ||||
| 		list->last = elem->prev; | ||||
| 	} | ||||
| 	if (elem->prev) | ||||
| 	{ | ||||
| 		elem->prev->next = elem->next; | ||||
| 	} | ||||
| 	if (elem->next) | ||||
| 	{ | ||||
| 		elem->next->prev = elem->prev; | ||||
| 	} | ||||
| 	m_free(elem); | ||||
| 	return item; | ||||
| } | ||||
							
								
								
									
										28
									
								
								list.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								list.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| #ifndef _DROPBEAR_LIST_H | ||||
| #define _DROPBEAR_LIST_H | ||||
| 
 | ||||
| struct _m_list; | ||||
| 
 | ||||
| struct _m_list_elem { | ||||
|     void *item; | ||||
| 	struct _m_list_elem *next; | ||||
| 	struct _m_list_elem *prev; | ||||
|     struct _m_list *list; | ||||
| }; | ||||
| 	 | ||||
| typedef struct _m_list_elem m_list_elem; | ||||
| 
 | ||||
| struct _m_list { | ||||
|     m_list_elem *first; | ||||
|     m_list_elem *last; | ||||
| }; | ||||
| 
 | ||||
| typedef struct _m_list m_list; | ||||
| 
 | ||||
| m_list * list_new(); | ||||
| void list_append(m_list *list, void *item); | ||||
| /* returns the item for the element removed */ | ||||
| void * list_remove(m_list_elem *elem); | ||||
| 
 | ||||
| 
 | ||||
| #endif /* _DROPBEAR_LIST_H */ | ||||
| @ -112,13 +112,13 @@ typedef struct cli_runopts { | ||||
| 	int backgrounded; | ||||
| 	int is_subsystem; | ||||
| #ifdef ENABLE_CLI_PUBKEY_AUTH | ||||
| 	struct SignKeyList *privkeys; /* Keys to use for public-key auth */ | ||||
| 	m_list *privkeys; /* Keys to use for public-key auth */ | ||||
| #endif | ||||
| #ifdef ENABLE_CLI_REMOTETCPFWD | ||||
| 	struct TCPFwdList * remotefwds; | ||||
| 	m_list * remotefwds; | ||||
| #endif | ||||
| #ifdef ENABLE_CLI_LOCALTCPFWD | ||||
| 	struct TCPFwdList * localfwds; | ||||
| 	m_list * localfwds; | ||||
| #endif | ||||
| #ifdef ENABLE_CLI_AGENTFWD | ||||
| 	int agent_fwd; | ||||
|  | ||||
| @ -261,7 +261,7 @@ struct clientsession { | ||||
| 									  info request from the server for | ||||
| 									  interactive auth.*/ | ||||
| #endif | ||||
| 	struct SignKeyList *lastprivkey; | ||||
| 	sign_key *lastprivkey; | ||||
| 
 | ||||
| 	int retval; /* What the command exit status was - we emulate it */ | ||||
| #if 0 | ||||
|  | ||||
							
								
								
									
										14
									
								
								signkey.c
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								signkey.c
									
									
									
									
									
								
							| @ -40,8 +40,10 @@ sign_key * new_sign_key() { | ||||
| #ifdef DROPBEAR_RSA | ||||
| 	ret->rsakey = NULL; | ||||
| #endif | ||||
| 	ret->filename = NULL; | ||||
| 	ret->type = DROPBEAR_SIGNKEY_NONE; | ||||
| 	ret->source = SIGNKEY_SOURCE_INVALID; | ||||
| 	return ret; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| /* Returns "ssh-dss" or "ssh-rsa" corresponding to the type. Exits fatally
 | ||||
| @ -81,6 +83,9 @@ int signkey_type_from_name(const char* name, int namelen) { | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	TRACE(("signkey_type_from_name unexpected key type.")) | ||||
| 	printhex("Key type", name, namelen); | ||||
| 
 | ||||
| 	return DROPBEAR_SIGNKEY_NONE; | ||||
| } | ||||
| 
 | ||||
| @ -101,8 +106,11 @@ int buf_get_pub_key(buffer *buf, sign_key *key, int *type) { | ||||
| 	m_free(ident); | ||||
| 
 | ||||
| 	if (*type != DROPBEAR_SIGNKEY_ANY && *type != keytype) { | ||||
| 		TRACE(("buf_get_pub_key bad type - got %d, expected %d", keytype, type)) | ||||
| 		return DROPBEAR_FAILURE; | ||||
| 	} | ||||
| 	 | ||||
| 	TRACE(("buf_get_pub_key keytype is %d")) | ||||
| 
 | ||||
| 	*type = keytype; | ||||
| 
 | ||||
| @ -255,6 +263,8 @@ void sign_key_free(sign_key *key) { | ||||
| 	key->rsakey = NULL; | ||||
| #endif | ||||
| 
 | ||||
| 	m_free(key->filename); | ||||
| 
 | ||||
| 	m_free(key); | ||||
| 	TRACE(("leave sign_key_free")) | ||||
| } | ||||
| @ -358,7 +368,6 @@ void buf_put_sign(buffer* buf, sign_key *key, int type, | ||||
| 		const unsigned char *data, unsigned int len) { | ||||
| 
 | ||||
| 	buffer *sigblob; | ||||
| 
 | ||||
| 	sigblob = buf_new(MAX_PUBKEY_SIZE); | ||||
| 
 | ||||
| #ifdef DROPBEAR_DSS | ||||
| @ -374,7 +383,6 @@ void buf_put_sign(buffer* buf, sign_key *key, int type, | ||||
| 	if (sigblob->len == 0) { | ||||
| 		dropbear_exit("non-matching signing type"); | ||||
| 	} | ||||
| 
 | ||||
| 	buf_setpos(sigblob, 0); | ||||
| 	buf_putstring(buf, buf_getptr(sigblob, sigblob->len), | ||||
| 			sigblob->len); | ||||
|  | ||||
							
								
								
									
										14
									
								
								signkey.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								signkey.h
									
									
									
									
									
								
							| @ -29,8 +29,22 @@ | ||||
| #include "dss.h" | ||||
| #include "rsa.h" | ||||
| 
 | ||||
| 
 | ||||
| /* Sources for signing keys */ | ||||
| typedef enum { | ||||
| 	SIGNKEY_SOURCE_RAW_FILE, | ||||
| 	SIGNKEY_SOURCE_AGENT, | ||||
| 	SIGNKEY_SOURCE_INVALID,	 | ||||
| } signkey_source; | ||||
| 
 | ||||
| struct SIGN_key { | ||||
| 
 | ||||
| 	int type; /* The type of key (dss or rsa) */ | ||||
| 	signkey_source source; | ||||
| 	char *filename; | ||||
| 	/* the buffer? for encrypted keys, so we can later get
 | ||||
| 	 * the private key portion */ | ||||
| 
 | ||||
| #ifdef DROPBEAR_DSS | ||||
| 	dss_key * dsskey; | ||||
| #endif | ||||
|  | ||||
							
								
								
									
										9
									
								
								tcpfwd.h
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								tcpfwd.h
									
									
									
									
									
								
							| @ -25,6 +25,7 @@ | ||||
| #define _TCPFWD_H | ||||
| 
 | ||||
| #include "channel.h" | ||||
| #include "list.h" | ||||
| 
 | ||||
| struct TCPListener { | ||||
| 
 | ||||
| @ -43,16 +44,13 @@ struct TCPListener { | ||||
| 	enum {direct, forwarded} tcp_type; | ||||
| }; | ||||
| 
 | ||||
| /* A link in a list of forwards */ | ||||
| struct TCPFwdList { | ||||
| 
 | ||||
| /* A forwarding entry */ | ||||
| struct TCPFwdEntry { | ||||
| 	const unsigned char* connectaddr; | ||||
| 	unsigned int connectport; | ||||
| 	unsigned int listenport; | ||||
| 	unsigned int have_reply; /* is set to 1 after a reply has been received
 | ||||
| 								when setting up the forwarding */ | ||||
| 	struct TCPFwdList * next; | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| /* Server */ | ||||
| @ -70,5 +68,4 @@ void cli_recv_msg_request_failure(); | ||||
| /* Common */ | ||||
| int listen_tcpfwd(struct TCPListener* tcpinfo); | ||||
| 
 | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user