From bb8234c2f12998b6cd9590f7dddd08d1871a5d1f Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Thu, 30 Jul 2009 15:14:33 +0000
Subject: [PATCH] Agent forwarding works

--HG--
branch : agent-client
extra : convert_revision : eb0dae4b62e243ba37a897beb7ba81a4f637d8b3
---
 agentfwd.h        | 10 ++++++----
 chansession.h     |  1 +
 cli-agentfwd.c    | 14 ++++++++++++--
 cli-authpubkey.c  |  5 ++---
 cli-chansession.c | 15 ++++++++++-----
 cli-session.c     |  2 +-
 dbclient.1        |  5 +++++
 debug.h           |  2 +-
 signkey.c         |  1 -
 svr-agentfwd.c    | 12 ++++++++----
 svr-chansession.c |  6 +++---
 11 files changed, 49 insertions(+), 24 deletions(-)

diff --git a/agentfwd.h b/agentfwd.h
index e1794a77..e9824605 100644
--- a/agentfwd.h
+++ b/agentfwd.h
@@ -35,14 +35,16 @@
  * 10000 is arbitrary */
 #define MAX_AGENT_REPLY  10000
 
-int agentreq(struct ChanSess * chansess);
-void agentcleanup(struct ChanSess * chansess);
-void agentset(struct ChanSess *chansess);
+int svr_agentreq(struct ChanSess * chansess);
+void svr_agentcleanup(struct ChanSess * chansess);
+void svr_agentset(struct ChanSess *chansess);
 
 /* client functions */
-void load_agent_keys(m_list * ret_list);
+void cli_load_agent_keys(m_list * ret_list);
 void agent_buf_sign(buffer *sigblob, sign_key *key, 
     const unsigned char *data, unsigned int len);
+void cli_setup_agent(struct Channel *channel);
+
 
 #ifdef __hpux
 #define seteuid(a)       setresuid(-1, (a), -1)
diff --git a/chansession.h b/chansession.h
index 8d8e1736..b9d19950 100644
--- a/chansession.h
+++ b/chansession.h
@@ -81,6 +81,7 @@ void cli_chansess_winchange();
 #ifdef ENABLE_CLI_NETCAT
 void cli_send_netcat_request();
 #endif
+void cli_start_send_channel_request(struct Channel *channel, unsigned char *type);
 
 void svr_chansessinitialise();
 extern const struct ChanType svrchansess;
diff --git a/cli-agentfwd.c b/cli-agentfwd.c
index ed2c59c1..c7df7881 100644
--- a/cli-agentfwd.c
+++ b/cli-agentfwd.c
@@ -226,10 +226,20 @@ out:
 	}
 }
 
+void cli_setup_agent(struct Channel *channel) {
+	if (!getenv("SSH_AUTH_SOCK")) {
+		return;
+	}
+	
+	cli_start_send_channel_request(channel, "auth-agent-req@openssh.com");
+	/* Don't want replies */
+	buf_putbyte(ses.writepayload, 0);
+	encrypt_packet();
+}
+
 /* Returned keys are prepended to ret_list, which will
    be updated. */
-void load_agent_keys(m_list *ret_list)
-{
+void cli_load_agent_keys(m_list *ret_list) {
 	/* agent_fd will be closed after successful auth */
 	cli_opts.agent_fd = connect_agent();
 	if (cli_opts.agent_fd < 0) {
diff --git a/cli-authpubkey.c b/cli-authpubkey.c
index a9906318..a57fd6b6 100644
--- a/cli-authpubkey.c
+++ b/cli-authpubkey.c
@@ -187,10 +187,9 @@ int cli_auth_pubkey() {
 
 	TRACE(("enter cli_auth_pubkey"))
 
-	if (cli_opts.agent_fwd &&
-			!cli_opts.agent_keys_loaded) {
+	if (!cli_opts.agent_keys_loaded) {
 		/* get the list of available keys from the agent */
-		load_agent_keys(cli_opts.privkeys);
+		cli_load_agent_keys(cli_opts.privkeys);
 		cli_opts.agent_keys_loaded = 1;
 	}
 
diff --git a/cli-chansession.c b/cli-chansession.c
index 9dc02249..2d97fea1 100644
--- a/cli-chansession.c
+++ b/cli-chansession.c
@@ -33,13 +33,12 @@
 #include "runopts.h"
 #include "termcodes.h"
 #include "chansession.h"
+#include "agentfwd.h"
 
 static void cli_closechansess(struct Channel *channel);
 static int cli_initchansess(struct Channel *channel);
 static void cli_chansessreq(struct Channel *channel);
 
-static void start_channel_request(struct Channel *channel, unsigned char *type);
-
 static void send_chansess_pty_req(struct Channel *channel);
 static void send_chansess_shell_req(struct Channel *channel);
 
@@ -92,7 +91,7 @@ static void cli_closechansess(struct Channel *UNUSED(channel)) {
 
 }
 
-static void start_channel_request(struct Channel *channel, 
+void cli_start_send_channel_request(struct Channel *channel, 
 		unsigned char *type) {
 
 	CHECKCLEARTOWRITE();
@@ -287,7 +286,7 @@ static void send_chansess_pty_req(struct Channel *channel) {
 
 	TRACE(("enter send_chansess_pty_req"))
 
-	start_channel_request(channel, "pty-req");
+	cli_start_send_channel_request(channel, "pty-req");
 
 	/* Don't want replies */
 	buf_putbyte(ses.writepayload, 0);
@@ -330,7 +329,7 @@ static void send_chansess_shell_req(struct Channel *channel) {
 		reqtype = "shell";
 	}
 
-	start_channel_request(channel, reqtype);
+	cli_start_send_channel_request(channel, reqtype);
 
 	/* XXX TODO */
 	buf_putbyte(ses.writepayload, 0); /* Don't want replies */
@@ -361,6 +360,12 @@ static int cli_initchansess(struct Channel *channel) {
 
 	cli_init_stdpipe_sess(channel);
 
+#ifdef ENABLE_CLI_AGENTFWD
+	if (cli_opts.agent_fwd) {
+		cli_setup_agent(channel);
+	}
+#endif
+
 	if (cli_opts.wantpty) {
 		send_chansess_pty_req(channel);
 	}
diff --git a/cli-session.c b/cli-session.c
index f9b372b2..ed58a119 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -235,7 +235,7 @@ static void cli_sessionloop() {
 				cli_send_netcat_request();
 			} else 
 #endif
-				if (!cli_opts.no_cmd) {
+			if (!cli_opts.no_cmd) {
 				cli_send_chansess_request();
 			}
 			TRACE(("leave cli_sessionloop: running"))
diff --git a/dbclient.1 b/dbclient.1
index 96e6c5c1..2065502e 100644
--- a/dbclient.1
+++ b/dbclient.1
@@ -82,6 +82,11 @@ by the ssh server.
 Always accept hostkeys if they are unknown. If a hostkey mismatch occurs the
 connection will abort as normal.
 .TP
+.B \-A
+Forward agent connections to the remote host. dbclient will use any
+OpenSSH-style agent program if available ($SSH_AUTH_SOCK will be set) for
+public key authentication.  Forwarding is only enabled if -A is specified.
+.TP
 .B \-W \fIwindowsize
 Specify the per-channel receive window buffer size. Increasing this 
 may improve network performance at the expense of memory use. Use -h to see the
diff --git a/debug.h b/debug.h
index a9cc0bd7..b8c2a575 100644
--- a/debug.h
+++ b/debug.h
@@ -39,7 +39,7 @@
  * Caution: Don't use this in an unfriendly environment (ie unfirewalled),
  * since the printing may not sanitise strings etc. This will add a reasonable
  * amount to your executable size. */
-#define DEBUG_TRACE
+/*#define DEBUG_TRACE*/
 
 /* All functions writing to the cleartext payload buffer call
  * CHECKCLEARTOWRITE() before writing. This is only really useful if you're
diff --git a/signkey.c b/signkey.c
index 9bc48457..612fd580 100644
--- a/signkey.c
+++ b/signkey.c
@@ -84,7 +84,6 @@ 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;
 }
diff --git a/svr-agentfwd.c b/svr-agentfwd.c
index b86c4474..940c4b7a 100644
--- a/svr-agentfwd.c
+++ b/svr-agentfwd.c
@@ -49,10 +49,12 @@ static void agentaccept(struct Listener * listener, int sock);
 
 /* Handles client requests to start agent forwarding, sets up listening socket.
  * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
-int agentreq(struct ChanSess * chansess) {
+int svr_agentreq(struct ChanSess * chansess) {
 
 	int fd;
 
+	TRACE(("enter svr_agentreq"))
+
 	if (!svr_pubkey_allows_agentfwd()) {
 		return DROPBEAR_FAILURE;
 	}
@@ -89,10 +91,12 @@ int agentreq(struct ChanSess * chansess) {
 	}
 
 	return DROPBEAR_SUCCESS;
+	TRACE(("success"))
 
 fail:
+	TRACE(("fail"))
 	/* cleanup */
-	agentcleanup(chansess);
+	svr_agentcleanup(chansess);
 
 	return DROPBEAR_FAILURE;
 }
@@ -118,7 +122,7 @@ static void agentaccept(struct Listener *UNUSED(listener), int sock) {
 
 /* set up the environment variable pointing to the socket. This is called
  * just before command/shell execution, after dropping priveleges */
-void agentset(struct ChanSess * chansess) {
+void svr_agentset(struct ChanSess * chansess) {
 
 	char *path = NULL;
 	int len;
@@ -137,7 +141,7 @@ void agentset(struct ChanSess * chansess) {
 }
 
 /* close the socket, remove the socket-file */
-void agentcleanup(struct ChanSess * chansess) {
+void svr_agentcleanup(struct ChanSess * chansess) {
 
 	char *path = NULL;
 	uid_t uid;
diff --git a/svr-chansession.c b/svr-chansession.c
index 23dad8c1..574e46f7 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -287,7 +287,7 @@ static void closechansess(struct Channel *channel) {
 #endif
 
 #ifndef DISABLE_AGENTFWD
-	agentcleanup(chansess);
+	svr_agentcleanup(chansess);
 #endif
 
 	/* clear child pid entries */
@@ -346,7 +346,7 @@ static void chansessionrequest(struct Channel *channel) {
 #endif
 #ifndef DISABLE_AGENTFWD
 	} else if (strcmp(type, "auth-agent-req@openssh.com") == 0) {
-		ret = agentreq(chansess);
+		ret = svr_agentreq(chansess);
 #endif
 	} else if (strcmp(type, "signal") == 0) {
 		ret = sessionsignal(chansess);
@@ -894,7 +894,7 @@ static void execchild(void *user_data) {
 #endif
 #ifndef DISABLE_AGENTFWD
 	/* set up agent env variable */
-	agentset(chansess);
+	svr_agentset(chansess);
 #endif
 
 	usershell = m_strdup(get_user_shell());
-- 
GitLab