mirror of
				https://github.com/clearml/dropbear
				synced 2025-06-26 18:17:32 +00:00 
			
		
		
		
	- Client auth using an agent's key works. Still need to implement client
agent forwarding. --HG-- branch : agent-client extra : convert_revision : 276cf5e82276b6c879d246ba64739ec6868f5150
This commit is contained in:
		
							parent
							
								
									c742137dc8
								
							
						
					
					
						commit
						8a19a049b2
					
				
							
								
								
									
										1
									
								
								auth.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								auth.h
									
									
									
									
									
								
							| @ -74,6 +74,7 @@ void cli_auth_password(); | ||||
| int cli_auth_pubkey(); | ||||
| void cli_auth_interactive(); | ||||
| char* getpass_or_cancel(char* prompt); | ||||
| void cli_auth_pubkey_cleanup(); | ||||
| 
 | ||||
| 
 | ||||
| #define MAX_USERNAME_LEN 25 /* arbitrary for the moment */ | ||||
|  | ||||
| @ -102,17 +102,26 @@ static int new_agent_chan(struct Channel * channel) { | ||||
|    data        Any data, depending on packet type.  Encoding as in the ssh packet | ||||
|                protocol. | ||||
| */ | ||||
| static buffer * agent_request(int fd, unsigned char type) { | ||||
| static buffer * agent_request(unsigned char type, buffer *data) { | ||||
| 
 | ||||
| 	buffer * payload = NULL; | ||||
| 	buffer * inbuf = NULL; | ||||
| 	size_t readlen = 0; | ||||
| 	ssize_t ret; | ||||
| 	const int fd = cli_opts.agent_fd; | ||||
| 	unsigned int data_len = 0; | ||||
| 	if (data) | ||||
| 	{ | ||||
| 		data_len = data->len; | ||||
| 	} | ||||
| 
 | ||||
| 	payload = buf_new(4 + 1); | ||||
| 	payload = buf_new(4 + 1 + data_len); | ||||
| 
 | ||||
| 	buf_putint(payload, 1); | ||||
| 	buf_putint(payload, 1 + data_len); | ||||
| 	buf_putbyte(payload, type); | ||||
| 	if (data) { | ||||
| 		buf_putbytes(payload, data->data, data->len); | ||||
| 	} | ||||
| 	buf_setpos(payload, 0); | ||||
| 
 | ||||
| 	ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len); | ||||
| @ -160,7 +169,7 @@ out: | ||||
| 	return inbuf; | ||||
| } | ||||
| 
 | ||||
| static void agent_get_key_list(int fd, m_list * ret_list) | ||||
| static void agent_get_key_list(m_list * ret_list) | ||||
| { | ||||
| 	buffer * inbuf = NULL; | ||||
| 	unsigned int num = 0; | ||||
| @ -168,9 +177,9 @@ static void agent_get_key_list(int fd, m_list * ret_list) | ||||
| 	unsigned int i; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES); | ||||
| 	inbuf = agent_request(SSH2_AGENTC_REQUEST_IDENTITIES, NULL); | ||||
| 	if (!inbuf) { | ||||
| 		TRACE(("agent_request returned no identities")) | ||||
| 		TRACE(("agent_request failed returning identities")) | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| @ -191,7 +200,6 @@ static void agent_get_key_list(int fd, m_list * ret_list) | ||||
| 		sign_key * pubkey = NULL; | ||||
| 		int key_type = DROPBEAR_SIGNKEY_ANY; | ||||
| 		buffer * key_buf; | ||||
| 		struct SignKeyList *nextkey = NULL; | ||||
| 
 | ||||
| 		/* each public key is encoded as a string */ | ||||
| 		key_buf = buf_getstringbuf(inbuf); | ||||
| @ -222,19 +230,66 @@ out: | ||||
|    be updated. */ | ||||
| void load_agent_keys(m_list *ret_list) | ||||
| { | ||||
| 	int fd; | ||||
| 	fd = connect_agent(); | ||||
| 	if (fd < 0) { | ||||
| 	/* agent_fd will be closed after successful auth */ | ||||
| 	cli_opts.agent_fd = connect_agent(); | ||||
| 	if (cli_opts.agent_fd < 0) { | ||||
| 		dropbear_log(LOG_INFO, "Failed to connect to agent"); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	agent_get_key_list(fd, ret_list); | ||||
| 	close(fd); | ||||
| 	agent_get_key_list(ret_list); | ||||
| } | ||||
| 
 | ||||
| void agent_buf_sign(buffer *sigblob, sign_key *key,  | ||||
| 		const unsigned char *data, unsigned int len) { | ||||
| 	buffer *request_data = buf_new(MAX_PUBKEY_SIZE + len + 12); | ||||
| 	buffer *response; | ||||
| 	unsigned int keylen, siglen; | ||||
| 	int packet_type; | ||||
| 	 | ||||
| 	/* Request format
 | ||||
| 	byte			SSH2_AGENTC_SIGN_REQUEST | ||||
| 	string			key_blob | ||||
| 	string			data | ||||
| 	uint32			flags | ||||
| 	*/ | ||||
| 	/* We write the key, then figure how long it was and write that */ | ||||
| 	//buf_putint(request_data, 0);
 | ||||
| 	buf_put_pub_key(request_data, key, key->type); | ||||
| 	keylen = request_data->len - 4; | ||||
| 	//buf_setpos(request_data, 0);
 | ||||
| 	//buf_putint(request_data, keylen);
 | ||||
| 	 | ||||
| 	//buf_setpos(request_data, request_data->len);
 | ||||
| 	buf_putstring(request_data, data, len); | ||||
| 	buf_putint(request_data, 0); | ||||
| 	 | ||||
| 	response = agent_request(SSH2_AGENTC_SIGN_REQUEST, request_data); | ||||
| 	buf_free(request_data); | ||||
| 	 | ||||
| 	if (!response) { | ||||
| 		goto fail; | ||||
| 	} | ||||
| 	 | ||||
| 	packet_type = buf_getbyte(response); | ||||
| 	if (packet_type != SSH2_AGENT_SIGN_RESPONSE) { | ||||
| 		goto fail; | ||||
| 	} | ||||
| 	 | ||||
| 	/* Response format
 | ||||
| 	byte			SSH2_AGENT_SIGN_RESPONSE | ||||
| 	string			signature_blob | ||||
| 	*/ | ||||
| 	siglen = buf_getint(response); | ||||
| 	buf_putbytes(sigblob, buf_getptr(response, siglen), siglen); | ||||
| 	buf_free(response); | ||||
| 	 | ||||
| 	return; | ||||
| fail: | ||||
| 	/* XXX don't fail badly here. instead propagate a failure code back up to
 | ||||
| 	   the cli auth pubkey code, and just remove this key from the list of  | ||||
| 	   ones to try. */ | ||||
| 	dropbear_exit("Agent failed signing key"); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
| @ -234,6 +234,10 @@ void recv_msg_userauth_success() { | ||||
| 	ses.authstate.authdone = 1; | ||||
| 	cli_ses.state = USERAUTH_SUCCESS_RCVD; | ||||
| 	cli_ses.lastauthtype = AUTH_TYPE_NONE; | ||||
| 
 | ||||
| #ifdef ENABLE_CLI_PUBKEY_AUTH | ||||
| 	cli_auth_pubkey_cleanup(); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void cli_auth_try() { | ||||
|  | ||||
| @ -174,7 +174,7 @@ static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) { | ||||
| 		sigbuf = buf_new(4 + SHA1_HASH_SIZE + ses.writepayload->len); | ||||
| 		buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE); | ||||
| 		buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len); | ||||
| 		buf_put_sign(ses.writepayload, key, type, sigbuf->data, sigbuf->len); | ||||
| 		cli_buf_put_sign(ses.writepayload, key, type, sigbuf->data, sigbuf->len); | ||||
| 		buf_free(sigbuf); /* Nothing confidential in the buffer */ | ||||
| 	} | ||||
| 
 | ||||
| @ -202,8 +202,22 @@ int cli_auth_pubkey() { | ||||
| 		TRACE(("leave cli_auth_pubkey-success")) | ||||
| 		return 1; | ||||
| 	} else { | ||||
| 		/* no more keys left */ | ||||
| 		TRACE(("leave cli_auth_pubkey-failure")) | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void cli_auth_pubkey_cleanup() { | ||||
| 
 | ||||
| #ifdef ENABLE_CLI_AGENTFWD | ||||
| 	m_close(cli_opts.agent_fd); | ||||
| 	cli_opts.agent_fd = -1; | ||||
| #endif | ||||
| 
 | ||||
| 	while (cli_opts.privkeys->first) { | ||||
| 		sign_key * key = list_remove(cli_opts.privkeys->first); | ||||
| 		sign_key_free(key); | ||||
| 	} | ||||
| } | ||||
| #endif /* Pubkey auth */ | ||||
|  | ||||
| @ -124,6 +124,8 @@ typedef struct cli_runopts { | ||||
| 	int agent_fwd; | ||||
| 	int agent_keys_loaded; /* whether pubkeys has been populated with a 
 | ||||
| 							  list of keys held by the agent */ | ||||
| 	int agent_fd; /* The agent fd is only set during authentication. Forwarded
 | ||||
| 	                 agent sessions have their own file descriptors */ | ||||
| #endif | ||||
| 
 | ||||
| #ifdef ENABLE_CLI_NETCAT | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user