summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Johnston <matt@ucc.asn.au>2009-07-06 14:02:45 +0000
committerMatt Johnston <matt@ucc.asn.au>2009-07-06 14:02:45 +0000
commit60c4f115efa9aa46c671ffaaf57e61b4b7de14f2 (patch)
tree4ab2dfaabab66d954baa7508e7f48d218472e54f
parent842e8f52e3cd511b48d4f46bbfd67b1c86f30733 (diff)
downloaddropbear-60c4f115efa9aa46c671ffaaf57e61b4b7de14f2.tar.gz
- Client auth using an agent's key works. Still need to implement client
agent forwarding.
-rw-r--r--auth.h1
-rw-r--r--cli-agentfwd.c79
-rw-r--r--cli-auth.c4
-rw-r--r--cli-authpubkey.c16
-rw-r--r--runopts.h2
5 files changed, 89 insertions, 13 deletions
diff --git a/auth.h b/auth.h
index d22f812..115000a 100644
--- a/auth.h
+++ b/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 */
diff --git a/cli-agentfwd.c b/cli-agentfwd.c
index 0a5661d..ed2c59c 100644
--- a/cli-agentfwd.c
+++ b/cli-agentfwd.c
@@ -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
diff --git a/cli-auth.c b/cli-auth.c
index 8b6a440..cfcf134 100644
--- a/cli-auth.c
+++ b/cli-auth.c
@@ -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() {
diff --git a/cli-authpubkey.c b/cli-authpubkey.c
index 0ad0031..a990631 100644
--- a/cli-authpubkey.c
+++ b/cli-authpubkey.c
@@ -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 */
diff --git a/runopts.h b/runopts.h
index e672a4e..22376c1 100644
--- a/runopts.h
+++ b/runopts.h
@@ -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