- (djm) Pick up LOGIN_PROGRAM from environment or PATH if not set by headers
 - (djm) OpenBSD CVS updates:
   - deraadt@cvs.openbsd.org 2000/08/18 20:07:23
     [ssh.c]
     accept remsh as a valid name as well; roman@buildpoint.com
   - deraadt@cvs.openbsd.org 2000/08/18 20:17:13
     [deattack.c crc32.c packet.c]
     rename crc32() to ssh_crc32() to avoid zlib name clash.  do not move to
     libz crc32 function yet, because it has ugly "long"'s in it;
     oneill@cs.sfu.ca
   - deraadt@cvs.openbsd.org 2000/08/18 20:26:08
     [scp.1 scp.c]
     -S prog support; tv@debian.org
   - deraadt@cvs.openbsd.org 2000/08/18 20:50:07
     [scp.c]
     knf
   - deraadt@cvs.openbsd.org 2000/08/18 20:57:33
     [log-client.c]
     shorten
   - markus@cvs.openbsd.org  2000/08/19 12:48:11
     [channels.c channels.h clientloop.c ssh.c ssh.h]
     support for ~. in ssh2
   - deraadt@cvs.openbsd.org 2000/08/19 15:29:40
     [crc32.h]
     proper prototype
   - markus@cvs.openbsd.org  2000/08/19 15:34:44
     [authfd.c authfd.h key.c key.h ssh-add.1 ssh-add.c ssh-agent.1]
     [ssh-agent.c ssh-keygen.c sshconnect1.c sshconnect2.c Makefile]
     [fingerprint.c fingerprint.h]
     add SSH2/DSA support to the agent and some other DSA related cleanups.
     (note that we cannot talk to ssh.com's ssh2 agents)
   - markus@cvs.openbsd.org  2000/08/19 15:55:52
     [channels.c channels.h clientloop.c]
     more ~ support for ssh2
   - markus@cvs.openbsd.org  2000/08/19 16:21:19
     [clientloop.c]
     oops
   - millert@cvs.openbsd.org 2000/08/20 12:25:53
     [session.c]
     We have to stash the result of get_remote_name_or_ip() before we
     close our socket or getpeername() will get EBADF and the process
     will exit.  Only a problem for "UseLogin yes".
   - millert@cvs.openbsd.org 2000/08/20 12:30:59
     [session.c]
     Only check /etc/nologin if "UseLogin no" since login(1) may have its
     own policy on determining who is allowed to login when /etc/nologin
     is present.  Also use the _PATH_NOLOGIN define.
   - millert@cvs.openbsd.org 2000/08/20 12:42:43
     [auth1.c auth2.c session.c ssh.c]
     Add calls to setusercontext() and login_get*().  We basically call
     setusercontext() in most places where previously we did a setlogin().
     Add default login.conf file and put root in the "daemon" login class.
   - millert@cvs.openbsd.org 2000/08/21 10:23:31
     [session.c]
     Fix incorrect PATH setting; noted by Markus.
diff --git a/sshconnect2.c b/sshconnect2.c
index 22ad39e..1f49067 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -28,7 +28,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: sshconnect2.c,v 1.16 2000/07/16 08:27:22 markus Exp $");
+RCSID("$OpenBSD: sshconnect2.c,v 1.17 2000/08/19 21:34:44 markus Exp $");
 
 #include <openssl/bn.h>
 #include <openssl/rsa.h>
@@ -54,6 +54,7 @@
 #include "dsa.h"
 #include "sshconnect.h"
 #include "authfile.h"
+#include "authfd.h"
 
 /* import */
 extern char *client_version_string;
@@ -291,7 +292,7 @@
     unsigned char **sigp, int *lenp,
     unsigned char *data, int datalen);
 
-void
+int
 ssh2_sign_and_send_pubkey(Key *k, sign_fn *do_sign,
     const char *server_user, const char *host, const char *service)
 {
@@ -299,6 +300,7 @@
 	unsigned char *blob, *signature;
 	int bloblen, slen;
 	int skip = 0;
+	int ret = -1;
 
 	dsa_make_key_blob(k, &blob, &bloblen);
 
@@ -323,8 +325,12 @@
 	buffer_put_string(&b, blob, bloblen);
 
 	/* generate signature */
-	do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
-	key_free(k); /* XXX */
+	ret = do_sign(k, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
+	if (ret == -1) {
+		xfree(blob);
+		buffer_free(&b);
+		return 0;
+	}
 #ifdef DEBUG_DSS
 	buffer_dump(&b);
 #endif
@@ -357,6 +363,8 @@
 	/* send */
 	packet_send();
 	packet_write_wait();
+
+	return 1;
 }
 
 int
@@ -364,6 +372,7 @@
     const char *server_user, const char *host, const char *service)
 {
 	Key *k;
+	int ret = 0;
 	struct stat st;
 
 	if (stat(filename, &st) != 0) {
@@ -389,13 +398,53 @@
 			return 0;
 		}
 	}
-	ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service);
-	return 1;
+	ret = ssh2_sign_and_send_pubkey(k, dsa_sign, server_user, host, service);
+	key_free(k);
+	return ret;
+}
+
+int agent_sign(
+    Key *key,
+    unsigned char **sigp, int *lenp,
+    unsigned char *data, int datalen)
+{
+	int ret = -1;
+	AuthenticationConnection *ac = ssh_get_authentication_connection();
+	if (ac != NULL) {
+		ret = ssh_agent_sign(ac, key, sigp, lenp, data, datalen);
+		ssh_close_authentication_connection(ac);
+	}
+	return ret;
+}
+
+int
+ssh2_try_agent(AuthenticationConnection *ac,
+    const char *server_user, const char *host, const char *service)
+{
+	static int called = 0;
+	char *comment;
+	Key *k;
+	int ret;
+
+	if (called == 0) {
+		k = ssh_get_first_identity(ac, &comment, 2);
+		called ++;
+	} else {
+		k = ssh_get_next_identity(ac, &comment, 2);
+	}
+	if (k == NULL)
+		return 0;
+	debug("trying DSA agent key %s", comment);
+	xfree(comment);
+	ret = ssh2_sign_and_send_pubkey(k, agent_sign, server_user, host, service);
+	key_free(k);
+	return ret;
 }
 
 void
 ssh_userauth2(const char *server_user, char *host)
 {
+	AuthenticationConnection *ac = ssh_get_authentication_connection();
 	int type;
 	int plen;
 	int sent;
@@ -450,12 +499,17 @@
 			debug("partial success");
 		if (options.dsa_authentication &&
 		    strstr(auths, "publickey") != NULL) {
-			while (i < options.num_identity_files2) {
-				sent = ssh2_try_pubkey(
-				    options.identity_files2[i++],
+			if (ac != NULL)
+				sent = ssh2_try_agent(ac,
 				    server_user, host, service);
-				if (sent)
-					break;
+			if (!sent) {
+				while (i < options.num_identity_files2) {
+					sent = ssh2_try_pubkey(
+					    options.identity_files2[i++],
+					    server_user, host, service);
+					if (sent)
+						break;
+				}
 			}
 		}
 		if (!sent) {
@@ -469,6 +523,8 @@
 			fatal("Permission denied (%s).", auths);
 		xfree(auths);
 	}
+	if (ac != NULL)
+		ssh_close_authentication_connection(ac);
 	packet_done();
 	debug("ssh-userauth2 successfull");
 }