- 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:
Matt Johnston 2009-07-06 14:02:45 +00:00
parent c742137dc8
commit 8a19a049b2
5 changed files with 89 additions and 13 deletions

1
auth.h
View File

@ -74,6 +74,7 @@ void cli_auth_password();
int cli_auth_pubkey(); int cli_auth_pubkey();
void cli_auth_interactive(); void cli_auth_interactive();
char* getpass_or_cancel(char* prompt); char* getpass_or_cancel(char* prompt);
void cli_auth_pubkey_cleanup();
#define MAX_USERNAME_LEN 25 /* arbitrary for the moment */ #define MAX_USERNAME_LEN 25 /* arbitrary for the moment */

View File

@ -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 data Any data, depending on packet type. Encoding as in the ssh packet
protocol. protocol.
*/ */
static buffer * agent_request(int fd, unsigned char type) { static buffer * agent_request(unsigned char type, buffer *data) {
buffer * payload = NULL; buffer * payload = NULL;
buffer * inbuf = NULL; buffer * inbuf = NULL;
size_t readlen = 0; size_t readlen = 0;
ssize_t ret; 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); buf_putbyte(payload, type);
if (data) {
buf_putbytes(payload, data->data, data->len);
}
buf_setpos(payload, 0); buf_setpos(payload, 0);
ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len); ret = atomicio(write, fd, buf_getptr(payload, payload->len), payload->len);
@ -160,7 +169,7 @@ out:
return inbuf; 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; buffer * inbuf = NULL;
unsigned int num = 0; unsigned int num = 0;
@ -168,9 +177,9 @@ static void agent_get_key_list(int fd, m_list * ret_list)
unsigned int i; unsigned int i;
int ret; int ret;
inbuf = agent_request(fd, SSH2_AGENTC_REQUEST_IDENTITIES); inbuf = agent_request(SSH2_AGENTC_REQUEST_IDENTITIES, NULL);
if (!inbuf) { if (!inbuf) {
TRACE(("agent_request returned no identities")) TRACE(("agent_request failed returning identities"))
goto out; goto out;
} }
@ -191,7 +200,6 @@ static void agent_get_key_list(int fd, m_list * ret_list)
sign_key * pubkey = NULL; sign_key * pubkey = NULL;
int key_type = DROPBEAR_SIGNKEY_ANY; int key_type = DROPBEAR_SIGNKEY_ANY;
buffer * key_buf; buffer * key_buf;
struct SignKeyList *nextkey = NULL;
/* each public key is encoded as a string */ /* each public key is encoded as a string */
key_buf = buf_getstringbuf(inbuf); key_buf = buf_getstringbuf(inbuf);
@ -222,19 +230,66 @@ out:
be updated. */ be updated. */
void load_agent_keys(m_list *ret_list) void load_agent_keys(m_list *ret_list)
{ {
int fd; /* agent_fd will be closed after successful auth */
fd = connect_agent(); cli_opts.agent_fd = connect_agent();
if (fd < 0) { if (cli_opts.agent_fd < 0) {
dropbear_log(LOG_INFO, "Failed to connect to agent"); dropbear_log(LOG_INFO, "Failed to connect to agent");
return; return;
} }
agent_get_key_list(fd, ret_list); agent_get_key_list(ret_list);
close(fd);
} }
void agent_buf_sign(buffer *sigblob, sign_key *key, void agent_buf_sign(buffer *sigblob, sign_key *key,
const unsigned char *data, unsigned int len) { 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 #endif

View File

@ -234,6 +234,10 @@ void recv_msg_userauth_success() {
ses.authstate.authdone = 1; ses.authstate.authdone = 1;
cli_ses.state = USERAUTH_SUCCESS_RCVD; cli_ses.state = USERAUTH_SUCCESS_RCVD;
cli_ses.lastauthtype = AUTH_TYPE_NONE; cli_ses.lastauthtype = AUTH_TYPE_NONE;
#ifdef ENABLE_CLI_PUBKEY_AUTH
cli_auth_pubkey_cleanup();
#endif
} }
void cli_auth_try() { void cli_auth_try() {

View File

@ -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); sigbuf = buf_new(4 + SHA1_HASH_SIZE + ses.writepayload->len);
buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE); buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE);
buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len); 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 */ buf_free(sigbuf); /* Nothing confidential in the buffer */
} }
@ -202,8 +202,22 @@ int cli_auth_pubkey() {
TRACE(("leave cli_auth_pubkey-success")) TRACE(("leave cli_auth_pubkey-success"))
return 1; return 1;
} else { } else {
/* no more keys left */
TRACE(("leave cli_auth_pubkey-failure")) TRACE(("leave cli_auth_pubkey-failure"))
return 0; 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 */ #endif /* Pubkey auth */

View File

@ -124,6 +124,8 @@ typedef struct cli_runopts {
int agent_fwd; int agent_fwd;
int agent_keys_loaded; /* whether pubkeys has been populated with a int agent_keys_loaded; /* whether pubkeys has been populated with a
list of keys held by the agent */ 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 #endif
#ifdef ENABLE_CLI_NETCAT #ifdef ENABLE_CLI_NETCAT