- Merged OpenBSD CVS changes:
   - [auth-krb4.c auth-passwd.c auth-skey.c ssh.
     move skey-auth from auth-passwd.c to auth-s
   - [auth-rsa.c]
     warn only about mismatch if key is _used_
     warn about keysize-mismatch with log() not
     channels.c readconf.c readconf.h ssh.c ssh.
     ports are u_short
   - [hostfile.c]
     indent, shorter warning
   - [nchan.c]
     use error() for internal errors
   - [packet.c]
     set loglevel for SSH_MSG_DISCONNECT to log(
     serverloop.c
     indent
   - [ssh-add.1 ssh-add.c ssh.h]
     document , reasonable default
   - [ssh.1]
     CheckHostIP is not available for connects v
   - [sshconnect.c]
     typo
     easier to read client code for passwd and s
     turn of checkhostip for proxy connects, sin
diff --git a/ChangeLog b/ChangeLog
index 69b5688..dc16db0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,29 @@
 19991204
  - Small cleanup of PAM code in sshd.c
+ - Merged OpenBSD CVS changes:
+   - [auth-krb4.c auth-passwd.c auth-skey.c ssh.h]
+     move skey-auth from auth-passwd.c to auth-skey.c, same for krb4
+   - [auth-rsa.c]
+     warn only about mismatch if key is _used_
+     warn about keysize-mismatch with log() not error()
+     channels.c readconf.c readconf.h ssh.c ssh.h sshconnect.c
+     ports are u_short
+   - [hostfile.c]
+     indent, shorter warning
+   - [nchan.c]
+     use error() for internal errors
+   - [packet.c]
+     set loglevel for SSH_MSG_DISCONNECT to log(), not fatal()
+     serverloop.c
+     indent
+   - [ssh-add.1 ssh-add.c ssh.h]
+     document $SSH_ASKPASS, reasonable default
+   - [ssh.1]
+     CheckHostIP is not available for connects via proxy command
+   - [sshconnect.c]
+     typo
+     easier to read client code for passwd and skey auth
+     turn of checkhostip for proxy connects, since we don't know the remote ip
 
 19991126
  - Add definition for __P()
diff --git a/auth-krb4.c b/auth-krb4.c
index 9f99533..fb0e20c 100644
--- a/auth-krb4.c
+++ b/auth-krb4.c
@@ -7,10 +7,123 @@
 #include "packet.h"
 #include "xmalloc.h"
 #include "ssh.h"
+#include "servconf.h"
 
 #ifdef KRB4
 char *ticket = NULL;
 
+extern ServerOptions options;
+
+/*
+ * try krb4 authentication,
+ * return 1 on success, 0 on failure, -1 if krb4 is not available
+ */
+
+int 
+auth_krb4_password(struct passwd * pw, const char *password)
+{
+	AUTH_DAT adata;
+	KTEXT_ST tkt;
+	struct hostent *hp;
+	unsigned long faddr;
+	char localhost[MAXHOSTNAMELEN];
+	char phost[INST_SZ];
+	char realm[REALM_SZ];
+	int r;
+
+	/*
+	 * Try Kerberos password authentication only for non-root
+	 * users and only if Kerberos is installed.
+	 */
+	if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
+
+		/* Set up our ticket file. */
+		if (!krb4_init(pw->pw_uid)) {
+			log("Couldn't initialize Kerberos ticket file for %s!",
+			    pw->pw_name);
+			goto kerberos_auth_failure;
+		}
+		/* Try to get TGT using our password. */
+		r = krb_get_pw_in_tkt((char *) pw->pw_name, "",
+		    realm, "krbtgt", realm,
+		    DEFAULT_TKT_LIFE, (char *) password);
+		if (r != INTK_OK) {
+			packet_send_debug("Kerberos V4 password "
+			    "authentication for %s failed: %s",
+			    pw->pw_name, krb_err_txt[r]);
+			goto kerberos_auth_failure;
+		}
+		/* Successful authentication. */
+		chown(tkt_string(), pw->pw_uid, pw->pw_gid);
+
+		/*
+		 * Now that we have a TGT, try to get a local
+		 * "rcmd" ticket to ensure that we are not talking
+		 * to a bogus Kerberos server.
+		 */
+		(void) gethostname(localhost, sizeof(localhost));
+		(void) strlcpy(phost, (char *) krb_get_phost(localhost),
+		    INST_SZ);
+		r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);
+
+		if (r == KSUCCESS) {
+			if (!(hp = gethostbyname(localhost))) {
+				log("Couldn't get local host address!");
+				goto kerberos_auth_failure;
+			}
+			memmove((void *) &faddr, (void *) hp->h_addr,
+			    sizeof(faddr));
+
+			/* Verify our "rcmd" ticket. */
+			r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost,
+			    faddr, &adata, "");
+			if (r == RD_AP_UNDEC) {
+				/*
+				 * Probably didn't have a srvtab on
+				 * localhost. Allow login.
+				 */
+				log("Kerberos V4 TGT for %s unverifiable, "
+				    "no srvtab installed? krb_rd_req: %s",
+				    pw->pw_name, krb_err_txt[r]);
+			} else if (r != KSUCCESS) {
+				log("Kerberos V4 %s ticket unverifiable: %s",
+				    KRB4_SERVICE_NAME, krb_err_txt[r]);
+				goto kerberos_auth_failure;
+			}
+		} else if (r == KDC_PR_UNKNOWN) {
+			/*
+			 * Allow login if no rcmd service exists, but
+			 * log the error.
+			 */
+			log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
+			    "not registered, or srvtab is wrong?", pw->pw_name,
+			krb_err_txt[r], KRB4_SERVICE_NAME, phost);
+		} else {
+			/*
+			 * TGT is bad, forget it. Possibly spoofed!
+			 */
+			packet_send_debug("WARNING: Kerberos V4 TGT "
+			    "possibly spoofed for %s: %s",
+			    pw->pw_name, krb_err_txt[r]);
+			goto kerberos_auth_failure;
+		}
+
+		/* Authentication succeeded. */
+		return 1;
+
+kerberos_auth_failure:
+		krb4_cleanup_proc(NULL);
+
+		if (!options.kerberos_or_local_passwd)
+			return 0;
+	} else {
+		/* Logging in as root or no local Kerberos realm. */
+		packet_send_debug("Unable to authenticate to Kerberos.");
+	}
+	/* Fall back to ordinary passwd authentication. */
+	return -1;
+}
+
 void
 krb4_cleanup_proc(void *ignore)
 {
diff --git a/auth-passwd.c b/auth-passwd.c
index e5574ff..efae0fd 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -11,7 +11,7 @@
 
 #ifndef HAVE_PAM
 
-RCSID("$Id: auth-passwd.c,v 1.7 1999/11/25 00:54:57 damien Exp $");
+RCSID("$Id: auth-passwd.c,v 1.8 1999/12/06 00:47:28 damien Exp $");
 
 #include "packet.h"
 #include "ssh.h"
@@ -49,133 +49,20 @@
 
 #ifdef SKEY
 	if (options.skey_authentication == 1) {
-		if (strncasecmp(password, "s/key", 5) == 0) {
-			char *skeyinfo = skey_keyinfo(pw->pw_name);
-			if (skeyinfo == NULL) {
-				debug("generating fake skeyinfo for %.100s.",
-				    pw->pw_name);
-				skeyinfo = skey_fake_keyinfo(pw->pw_name);
-			}
-			if (skeyinfo != NULL)
-				packet_send_debug(skeyinfo);
-			/* Try again. */
-			return 0;
-		} else if (skey_haskey(pw->pw_name) == 0 &&
-			   skey_passcheck(pw->pw_name, (char *) password) != -1) {
-			/* Authentication succeeded. */
-			return 1;
-		}
+		int ret = auth_skey_password(pw, password);
+		if (ret == 1 || ret == 0)
+			return ret;
 		/* Fall back to ordinary passwd authentication. */
 	}
 #endif
-
-#if defined(KRB4)
-	/*
-	 * Support for Kerberos v4 authentication
-	 * - Dug Song <dugsong@UMICH.EDU>
-	 */
-	if (options.kerberos_authentication) {
-		AUTH_DAT adata;
-		KTEXT_ST tkt;
-		struct hostent *hp;
-		unsigned long faddr;
-		char localhost[MAXHOSTNAMELEN];
-		char phost[INST_SZ];
-		char realm[REALM_SZ];
-		int r;
-
-		/*
-		 * Try Kerberos password authentication only for non-root
-		 * users and only if Kerberos is installed.
-		 */
-		if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
-
-			/* Set up our ticket file. */
-			if (!krb4_init(pw->pw_uid)) {
-				log("Couldn't initialize Kerberos ticket file for %s!",
-				    pw->pw_name);
-				goto kerberos_auth_failure;
-			}
-			/* Try to get TGT using our password. */
-			r = krb_get_pw_in_tkt((char *) pw->pw_name, "",
-			    realm, "krbtgt", realm,
-			    DEFAULT_TKT_LIFE, (char *) password);
-			if (r != INTK_OK) {
-				packet_send_debug("Kerberos V4 password "
-				    "authentication for %s failed: %s",
-				    pw->pw_name, krb_err_txt[r]);
-				goto kerberos_auth_failure;
-			}
-			/* Successful authentication. */
-			chown(tkt_string(), pw->pw_uid, pw->pw_gid);
-
-			/*
-			 * Now that we have a TGT, try to get a local
-			 * "rcmd" ticket to ensure that we are not talking
-			 * to a bogus Kerberos server.
-			 */
-			(void) gethostname(localhost, sizeof(localhost));
-			(void) strlcpy(phost, (char *) krb_get_phost(localhost),
-			    INST_SZ);
-			r = krb_mk_req(&tkt, KRB4_SERVICE_NAME, phost, realm, 33);
-
-			if (r == KSUCCESS) {
-				if (!(hp = gethostbyname(localhost))) {
-					log("Couldn't get local host address!");
-					goto kerberos_auth_failure;
-				}
-				memmove((void *) &faddr, (void *) hp->h_addr,
-				    sizeof(faddr));
-
-				/* Verify our "rcmd" ticket. */
-				r = krb_rd_req(&tkt, KRB4_SERVICE_NAME, phost,
-				    faddr, &adata, "");
-				if (r == RD_AP_UNDEC) {
-					/*
-					 * Probably didn't have a srvtab on
-					 * localhost. Allow login.
-					 */
-					log("Kerberos V4 TGT for %s unverifiable, "
-					    "no srvtab installed? krb_rd_req: %s",
-					    pw->pw_name, krb_err_txt[r]);
-				} else if (r != KSUCCESS) {
-					log("Kerberos V4 %s ticket unverifiable: %s",
-					    KRB4_SERVICE_NAME, krb_err_txt[r]);
-					goto kerberos_auth_failure;
-				}
-			} else if (r == KDC_PR_UNKNOWN) {
-				/*
-				 * Allow login if no rcmd service exists, but
-				 * log the error.
-				 */
-				log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
-				    "not registered, or srvtab is wrong?", pw->pw_name,
-				krb_err_txt[r], KRB4_SERVICE_NAME, phost);
-			} else {
-				/*
-				 * TGT is bad, forget it. Possibly spoofed!
-				 */
-				packet_send_debug("WARNING: Kerberos V4 TGT "
-				    "possibly spoofed for %s: %s",
-				    pw->pw_name, krb_err_txt[r]);
-				goto kerberos_auth_failure;
-			}
-
-			/* Authentication succeeded. */
-			return 1;
-
-	kerberos_auth_failure:
-			krb4_cleanup_proc(NULL);
-
-			if (!options.kerberos_or_local_passwd)
-				return 0;
-		} else {
-			/* Logging in as root or no local Kerberos realm. */
-			packet_send_debug("Unable to authenticate to Kerberos.");
-		}
+#ifdef KRB4
+	if (options.kerberos_authentication == 1) {
+		int ret = auth_krb4_password(pw, password);
+		if (ret == 1 || ret == 0)
+			return ret;
 		/* Fall back to ordinary passwd authentication. */
 	}
-#endif				/* KRB4 */
+#endif
 
 	/* Check for users with no password. */
 	if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
diff --git a/auth-rsa.c b/auth-rsa.c
index 88dc2e7..bc53b04 100644
--- a/auth-rsa.c
+++ b/auth-rsa.c
@@ -16,7 +16,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: auth-rsa.c,v 1.10 1999/11/25 00:54:57 damien Exp $");
+RCSID("$Id: auth-rsa.c,v 1.11 1999/12/06 00:47:28 damien Exp $");
 
 #include "rsa.h"
 #include "packet.h"
@@ -259,16 +259,16 @@
 		}
 		/* cp now points to the comment part. */
 
-		/* check the real bits  */
-		if (bits != BN_num_bits(n))
-			error("Warning: error in %s, line %ld: keysize mismatch: "
-			      "actual size %d vs. announced %d.",
-			      file, linenum, BN_num_bits(n), bits);
-
 		/* Check if the we have found the desired key (identified by its modulus). */
 		if (BN_cmp(n, client_n) != 0)
 			continue;
 
+		/* check the real bits  */
+		if (bits != BN_num_bits(n))
+			log("Warning: %s, line %ld: keysize mismatch: "
+			    "actual %d vs. announced %d.",
+			    file, linenum, BN_num_bits(n), bits);
+
 		/* We have found the desired key. */
 
 		/* Perform the challenge-response dialog for this key. */
diff --git a/auth-skey.c b/auth-skey.c
index a0d786c..cc5f451 100644
--- a/auth-skey.c
+++ b/auth-skey.c
@@ -1,9 +1,11 @@
 #include "includes.h"
 
 #ifdef SKEY
-RCSID("$Id: auth-skey.c,v 1.3 1999/11/23 22:25:52 markus Exp $");
+RCSID("$Id: auth-skey.c,v 1.4 1999/12/01 16:54:35 markus Exp $");
 
 #include "ssh.h"
+#include "packet.h"
+
 #ifdef HAVE_OPENSSL
 #include <openssl/sha1.h>
 #endif
@@ -13,6 +15,35 @@
 
 /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
 
+/* 
+ * try skey authentication,
+ * return 1 on success, 0 on failure, -1 if skey is not available 
+ */
+
+int 
+auth_skey_password(struct passwd * pw, const char *password)
+{
+	if (strncasecmp(password, "s/key", 5) == 0) {
+		char *skeyinfo = skey_keyinfo(pw->pw_name);
+		if (skeyinfo == NULL) {
+			debug("generating fake skeyinfo for %.100s.",
+			    pw->pw_name);
+			skeyinfo = skey_fake_keyinfo(pw->pw_name);
+		}
+		if (skeyinfo != NULL)
+			packet_send_debug(skeyinfo);
+		/* Try again. */
+		return 0;
+	} else if (skey_haskey(pw->pw_name) == 0 &&
+		   skey_passcheck(pw->pw_name, (char *) password) != -1) {
+		/* Authentication succeeded. */
+		return 1;
+	}
+	/* Fall back to ordinary passwd authentication. */
+	return -1;
+}
+  
++ /* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */
 
 #define ROUND(x)   (((x)[0] << 24) + (((x)[1]) << 16) + (((x)[2]) << 8) + \
 		    ((x)[3]))
diff --git a/channels.c b/channels.c
index 61ba76d..0138236 100644
--- a/channels.c
+++ b/channels.c
@@ -16,7 +16,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: channels.c,v 1.8 1999/11/25 00:54:58 damien Exp $");
+RCSID("$Id: channels.c,v 1.9 1999/12/06 00:47:29 damien Exp $");
 
 #include "ssh.h"
 #include "packet.h"
@@ -82,7 +82,7 @@
  */
 typedef struct {
 	char *host;		/* Host name. */
-	int port;		/* Port number. */
+	u_short port;		/* Port number. */
 } ForwardPermission;
 
 /* List of all permitted host/port pairs to connect. */
@@ -876,8 +876,8 @@
  */
 
 void 
-channel_request_local_forwarding(int port, const char *host,
-				 int host_port)
+channel_request_local_forwarding(u_short port, const char *host,
+				 u_short host_port)
 {
 	int ch, sock, on = 1;
 	struct sockaddr_in sin;
@@ -932,8 +932,8 @@
  */
 
 void 
-channel_request_remote_forwarding(int port, const char *host,
-				  int remote_port)
+channel_request_remote_forwarding(u_short port, const char *host,
+				  u_short remote_port)
 {
 	int payload_len;
 	/* Record locally that connection to this host/port is permitted. */
@@ -968,7 +968,7 @@
 void 
 channel_input_port_forward_request(int is_root)
 {
-	int port, host_port;
+	u_short port, host_port;
 	char *hostname;
 
 	/* Get arguments from the packet. */
@@ -976,10 +976,6 @@
 	hostname = packet_get_string(NULL);
 	host_port = packet_get_int();
 
-	/* Port numbers are 16 bit quantities. */
-	if ((port & 0xffff) != port)
-		packet_disconnect("Requested forwarding of nonexistent port %d.", port);
-
 	/*
 	 * Check that an unprivileged user is not trying to forward a
 	 * privileged port.
@@ -1004,7 +1000,8 @@
 void 
 channel_input_port_open(int payload_len)
 {
-	int remote_channel, sock, newch, host_port, i;
+	int remote_channel, sock, newch, i;
+	u_short host_port;
 	struct sockaddr_in sin;
 	char *host, *originator_string;
 	struct hostent *hp;
@@ -1122,7 +1119,8 @@
 x11_create_display_inet(int screen_number)
 {
 	extern ServerOptions options;
-	int display_number, port, sock;
+	int display_number, sock;
+	u_short port;
 	struct sockaddr_in sin;
 	char buf[512];
 	char hostname[MAXHOSTNAMELEN];
diff --git a/hostfile.c b/hostfile.c
index cdfb48f..7060a89 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -14,7 +14,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: hostfile.c,v 1.6 1999/11/25 00:54:59 damien Exp $");
+RCSID("$OpenBSD: hostfile.c,v 1.10 1999/12/02 20:18:59 markus Exp $");
 
 #include "packet.h"
 #include "ssh.h"
@@ -231,9 +231,9 @@
 			continue;
 
 		if (kbits != BN_num_bits(kn)) {
-			error("Warning: error in %s, line %d: keysize mismatch for host %s: "
-			      "actual size %d vs. announced %d.",
-			filename, linenum, host, BN_num_bits(kn), kbits);
+			error("Warning: %s, line %d: keysize mismatch for host %s: "
+			      "actual %d vs. announced %d.",
+			      filename, linenum, host, BN_num_bits(kn), kbits);
 			error("Warning: replace %d with %d in %s, line %d.",
 			      kbits, BN_num_bits(kn), filename, linenum);
 		}
diff --git a/nchan.c b/nchan.c
index 065b69b..23d180c 100644
--- a/nchan.c
+++ b/nchan.c
@@ -28,7 +28,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: nchan.c,v 1.3 1999/11/25 00:54:59 damien Exp $");
+RCSID("$Id: nchan.c,v 1.4 1999/12/06 00:47:29 damien Exp $");
 
 #include "ssh.h"
 
@@ -65,7 +65,7 @@
 		chan_delele_if_full_closed(c);
 		break;
 	default:
-		debug("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
+		error("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
 		break;
 	}
 }
@@ -79,7 +79,7 @@
 		c->istate = CHAN_INPUT_WAIT_DRAIN;
 		break;
 	default:
-		debug("internal error: we do not read, but chan_read_failed %d for istate %d",
+		error("internal error: we do not read, but chan_read_failed %d for istate %d",
 		      c->self, c->istate);
 		break;
 	}
@@ -88,7 +88,7 @@
 chan_ibuf_empty(Channel *c)
 {
 	if (buffer_len(&c->input)) {
-		debug("internal error: chan_ibuf_empty %d for non empty buffer", c->self);
+		error("internal error: chan_ibuf_empty %d for non empty buffer", c->self);
 		return;
 	}
 	switch (c->istate) {
@@ -98,7 +98,7 @@
 		c->istate = CHAN_INPUT_WAIT_OCLOSE;
 		break;
 	default:
-		debug("internal error: chan_ibuf_empty %d for istate %d", c->self, c->istate);
+		error("internal error: chan_ibuf_empty %d for istate %d", c->self, c->istate);
 		break;
 	}
 }
@@ -118,7 +118,7 @@
 		chan_delele_if_full_closed(c);
 		break;
 	default:
-		debug("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
+		error("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
 		break;
 	}
 }
@@ -138,7 +138,7 @@
 		chan_delele_if_full_closed(c);
 		break;
 	default:
-		debug("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
+		error("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
 		break;
 	}
 }
@@ -157,7 +157,7 @@
 		chan_delele_if_full_closed(c);
 		break;
 	default:
-		debug("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
+		error("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
 		break;
 	}
 }
@@ -176,7 +176,7 @@
 		packet_send();
 		break;
 	default:
-		debug("internal error: channel %d: cannot send IEOF for istate %d", c->self, c->istate);
+		error("internal error: channel %d: cannot send IEOF for istate %d", c->self, c->istate);
 		break;
 	}
 }
@@ -193,7 +193,7 @@
 		packet_send();
 		break;
 	default:
-		debug("internal error: channel %d: cannot send OCLOSE for ostate %d", c->self, c->istate);
+		error("internal error: channel %d: cannot send OCLOSE for ostate %d", c->self, c->istate);
 		break;
 	}
 }
diff --git a/packet.c b/packet.c
index f4b44f5..9e8cf2e 100644
--- a/packet.c
+++ b/packet.c
@@ -15,7 +15,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: packet.c,v 1.6 1999/11/25 00:54:59 damien Exp $");
+RCSID("$Id: packet.c,v 1.7 1999/12/06 00:47:29 damien Exp $");
 
 #include "xmalloc.h"
 #include "buffer.h"
@@ -530,8 +530,10 @@
 	*payload_len_ptr = buffer_len(&incoming_packet);
 
 	/* Handle disconnect message. */
-	if ((unsigned char) buf[0] == SSH_MSG_DISCONNECT)
-		fatal("Received disconnect: %.900s", packet_get_string(NULL));
+	if ((unsigned char) buf[0] == SSH_MSG_DISCONNECT) {
+		log("Received disconnect: %.900s", packet_get_string(NULL));
+		fatal_cleanup();
+	}	
 
 	/* Ignore ignore messages. */
 	if ((unsigned char) buf[0] == SSH_MSG_IGNORE)
@@ -662,7 +664,8 @@
 	packet_close();
 
 	/* Display the error locally and exit. */
-	fatal("Disconnecting: %.100s", buf);
+	log("Disconnecting: %.100s", buf);
+	fatal_cleanup();
 }
 
 /* Checks if there is any buffered output, and tries to write some of the output. */
diff --git a/readconf.c b/readconf.c
index 2c27050..0ba7863 100644
--- a/readconf.c
+++ b/readconf.c
@@ -14,7 +14,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: readconf.c,v 1.6 1999/11/25 00:54:59 damien Exp $");
+RCSID("$Id: readconf.c,v 1.7 1999/12/06 00:47:29 damien Exp $");
 
 #include "ssh.h"
 #include "cipher.h"
@@ -164,13 +164,11 @@
  */
 
 void 
-add_local_forward(Options *options, int port, const char *host,
-		  int host_port)
+add_local_forward(Options *options, u_short port, const char *host,
+		  u_short host_port)
 {
 	Forward *fwd;
 	extern uid_t original_real_uid;
-	if ((port & 0xffff) != port)
-		fatal("Requested forwarding of nonexistent port %d.", port);
 	if (port < IPPORT_RESERVED && original_real_uid != 0)
 		fatal("Privileged ports can only be forwarded by root.\n");
 	if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
@@ -187,8 +185,8 @@
  */
 
 void 
-add_remote_forward(Options *options, int port, const char *host,
-		   int host_port)
+add_remote_forward(Options *options, u_short port, const char *host,
+		   u_short host_port)
 {
 	Forward *fwd;
 	if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
@@ -230,7 +228,8 @@
 		    int *activep)
 {
 	char buf[256], *cp, *string, **charptr, *cp2;
-	int opcode, *intptr, value, fwd_port, fwd_host_port;
+	int opcode, *intptr, value;
+	u_short fwd_port, fwd_host_port;
 
 	/* Skip leading whitespace. */
 	cp = line + strspn(line, WHITESPACE);
@@ -467,7 +466,7 @@
 		if (!cp)
 			fatal("%.200s line %d: Missing second argument.",
 			      filename, linenum);
-		if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
+		if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
 			fatal("%.200s line %d: Badly formatted host:port.",
 			      filename, linenum);
 		if (*activep)
@@ -486,7 +485,7 @@
 		if (!cp)
 			fatal("%.200s line %d: Missing second argument.",
 			      filename, linenum);
-		if (sscanf(cp, "%255[^:]:%d", buf, &fwd_host_port) != 2)
+		if (sscanf(cp, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
 			fatal("%.200s line %d: Badly formatted host:port.",
 			      filename, linenum);
 		if (*activep)
diff --git a/readconf.h b/readconf.h
index d594a46..09f0514 100644
--- a/readconf.h
+++ b/readconf.h
@@ -13,7 +13,7 @@
  * 
  */
 
-/* RCSID("$Id: readconf.h,v 1.5 1999/11/25 00:54:59 damien Exp $"); */
+/* RCSID("$Id: readconf.h,v 1.6 1999/12/06 00:47:29 damien Exp $"); */
 
 #ifndef READCONF_H
 #define READCONF_H
@@ -21,9 +21,9 @@
 /* Data structure for representing a forwarding request. */
 
 typedef struct {
-	int     port;		/* Port to forward. */
-	char   *host;		/* Host to connect. */
-	int     host_port;	/* Port to connect on host. */
+	u_short	  port;		/* Port to forward. */
+	char	 *host;		/* Host to connect. */
+	u_short	  host_port;	/* Port to connect on host. */
 }       Forward;
 /* Data structure for representing option data. */
 
@@ -123,15 +123,15 @@
  * error.
  */
 void 
-add_local_forward(Options * options, int port, const char *host,
-    int host_port);
+add_local_forward(Options * options, u_short port, const char *host,
+    u_short host_port);
 
 /*
  * Adds a remote TCP/IP port forward to options.  Never returns if there is
  * an error.
  */
 void 
-add_remote_forward(Options * options, int port, const char *host,
-    int host_port);
+add_remote_forward(Options * options, u_short port, const char *host,
+    u_short host_port);
 
 #endif				/* READCONF_H */
diff --git a/serverloop.c b/serverloop.c
index 683598e..94c2115 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -609,7 +609,7 @@
 		/* Check if it matches the process we forked. */
 		if (wait_pid != pid)
 			error("Strange, wait returned pid %d, expected %d",
-			    wait_pid, pid);
+			       wait_pid, pid);
 	}
 
 	/* We no longer want our SIGCHLD handler to be called. */
diff --git a/ssh-add.1 b/ssh-add.1
index 67e09b4..444af94 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -9,7 +9,7 @@
 .\"
 .\" Created: Sat Apr 22 23:55:14 1995 ylo
 .\"
-.\" $Id: ssh-add.1,v 1.5 1999/11/25 00:54:59 damien Exp $
+.\" $Id: ssh-add.1,v 1.6 1999/12/06 00:47:29 damien Exp $
 .\"
 .Dd September 25, 1999
 .Dt SSH-ADD 1
@@ -51,7 +51,7 @@
 .El
 .Sh FILES
 .Bl -tag -width Ds
-.Pa $HOME/.ssh/identity
+.It Pa $HOME/.ssh/identity
 Contains the RSA authentication identity of the user.  This file
 should not be readable by anyone but the user.
 Note that
@@ -64,6 +64,9 @@
 .Nm
 when no other files have been specified.
 .Pp
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev "DISPLAY" and "SSH_ASKPASS"
 If
 .Nm
 needs a passphrase, it will read the passphrase from the current
diff --git a/ssh-add.c b/ssh-add.c
index 2d0dad4..f01cca5 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -7,7 +7,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: ssh-add.c,v 1.15 1999/11/25 01:31:26 damien Exp $");
+RCSID("$Id: ssh-add.c,v 1.16 1999/12/06 00:47:29 damien Exp $");
 
 #include "rsa.h"
 #include "ssh.h"
@@ -106,8 +106,12 @@
 	}
 	RSA_free(public_key);
 
-	if (!interactive && getenv("DISPLAY"))
-		askpass = getenv("SSH_ASKPASS");
+	if (!interactive && getenv("DISPLAY")) {
+		if (getenv(SSH_ASKPASS_ENV))
+			askpass = getenv(SSH_ASKPASS_ENV);
+		else
+			askpass = SSH_ASKPASS_DEFAULT;
+	}
 
 	/* At first, try empty passphrase */
 	success = load_private_key(filename, "", key, &comment);
diff --git a/ssh.1 b/ssh.1
index 537a6e0..fb50444 100644
--- a/ssh.1
+++ b/ssh.1
@@ -9,7 +9,7 @@
 .\"
 .\" Created: Sat Apr 22 21:55:14 1995 ylo
 .\"
-.\" $Id: ssh.1,v 1.10 1999/11/25 00:54:59 damien Exp $
+.\" $Id: ssh.1,v 1.11 1999/12/06 00:47:29 damien Exp $
 .\"
 .Dd September 25, 1999
 .Dt SSH 1
@@ -627,6 +627,9 @@
 somewhere.  Host key management will be done using the
 HostName of the host being connected (defaulting to the name typed by
 the user).
+Note that
+.Cm CheckHostIP
+is not available for connects with a proxy command.
 .Pp
 .It Cm RemoteForward
 Specifies that a TCP/IP port on the remote machine be forwarded over
diff --git a/ssh.c b/ssh.c
index 21147f7..c0d61f8 100644
--- a/ssh.c
+++ b/ssh.c
@@ -11,7 +11,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: ssh.c,v 1.12 1999/11/25 00:54:59 damien Exp $");
+RCSID("$Id: ssh.c,v 1.13 1999/12/06 00:47:29 damien Exp $");
 
 #include "xmalloc.h"
 #include "ssh.h"
@@ -162,8 +162,8 @@
 int
 main(int ac, char **av)
 {
-	int i, opt, optind, type, exit_status, ok, fwd_port, fwd_host_port,
-	 authfd;
+	int i, opt, optind, type, exit_status, ok, authfd;
+	u_short fwd_port, fwd_host_port;
 	char *optarg, *cp, buf[256];
 	Buffer command;
 	struct winsize ws;
@@ -340,10 +340,6 @@
 
 		case 'p':
 			options.port = atoi(optarg);
-			if (options.port < 1 || options.port > 65535) {
-				fprintf(stderr, "Bad port %s.\n", optarg);
-				exit(1);
-			}
 			break;
 
 		case 'l':
@@ -351,7 +347,7 @@
 			break;
 
 		case 'R':
-			if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
+			if (sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf,
 				   &fwd_host_port) != 3) {
 				fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
 				usage();
@@ -361,7 +357,7 @@
 			break;
 
 		case 'L':
-			if (sscanf(optarg, "%d:%255[^:]:%d", &fwd_port, buf,
+			if (sscanf(optarg, "%hu:%255[^:]:%hu", &fwd_port, buf,
 				   &fwd_host_port) != 3) {
 				fprintf(stderr, "Bad forwarding specification '%s'.\n", optarg);
 				usage();
@@ -561,7 +557,7 @@
 	/* Check if the connection failed, and try "rsh" if appropriate. */
 	if (!ok) {
 		if (options.port != 0)
-			log("Secure connection to %.100s on port %d refused%.100s.",
+			log("Secure connection to %.100s on port %hu refused%.100s.",
 			    host, options.port,
 			    options.fallback_to_rsh ? "; reverting to insecure method" : "");
 		else
diff --git a/ssh.h b/ssh.h
index e3fed05..961c82a 100644
--- a/ssh.h
+++ b/ssh.h
@@ -13,7 +13,7 @@
  * 
  */
 
-/* RCSID("$Id: ssh.h,v 1.16 1999/11/25 00:54:59 damien Exp $"); */
+/* RCSID("$Id: ssh.h,v 1.17 1999/12/06 00:47:29 damien Exp $"); */
 
 #ifndef SSH_H
 #define SSH_H
@@ -170,6 +170,13 @@
 #define SSH_AGENTPID_ENV_NAME	"SSH_AGENT_PID"
 
 /*
+ * Default path to ssh-askpass used by ssh-add,
+ * environment variable for overwriting the default location
+ */
+#define SSH_ASKPASS_DEFAULT	"/usr/X11R6/bin/ssh-askpass"
+#define SSH_ASKPASS_ENV		"SSH_ASKPASS"
+
+/*
  * Force host key length and server key length to differ by at least this
  * many bits.  This is to make double encryption with rsaref work.
  */
@@ -294,7 +301,7 @@
  */
 int 
 ssh_connect(const char *host, struct sockaddr_in * hostaddr,
-    int port, int connection_attempts,
+    u_short port, int connection_attempts,
     int anonymous, uid_t original_real_uid,
     const char *proxy_command);
 
@@ -579,8 +586,8 @@
  * error.
  */
 void 
-channel_request_local_forwarding(int port, const char *host,
-    int remote_port);
+channel_request_local_forwarding(u_short port, const char *host,
+    u_short remote_port);
 
 /*
  * Initiate forwarding of connections to port "port" on remote host through
@@ -589,8 +596,8 @@
  * permitted.
  */
 void 
-channel_request_remote_forwarding(int port, const char *host,
-    int remote_port);
+channel_request_remote_forwarding(u_short port, const char *host,
+    u_short remote_port);
 
 /*
  * Permits opening to any host/port in SSH_MSG_PORT_OPEN.  This is usually
@@ -704,6 +711,7 @@
 int     auth_krb4(const char *server_user, KTEXT auth, char **client);
 int     krb4_init(uid_t uid);
 void    krb4_cleanup_proc(void *ignore);
+int	auth_krb4_password(struct passwd * pw, const char *password);
 
 #ifdef AFS
 #include <kafs.h>
@@ -721,6 +729,7 @@
 #ifdef SKEY
 #include <skey.h>
 char   *skey_fake_keyinfo(char *username);
+int	auth_skey_password(struct passwd * pw, const char *password);
 #endif				/* SKEY */
 
 #endif				/* SSH_H */
diff --git a/sshconnect.c b/sshconnect.c
index 0b1c090..593eade 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -8,7 +8,7 @@
  */
 
 #include "includes.h"
-RCSID("$Id: sshconnect.c,v 1.15 1999/11/25 00:54:59 damien Exp $");
+RCSID("$Id: sshconnect.c,v 1.16 1999/12/06 00:47:29 damien Exp $");
 
 #ifdef HAVE_OPENSSL
 #include <openssl/bn.h>
@@ -34,11 +34,13 @@
 /* Session id for the current session. */
 unsigned char session_id[16];
 
+extern Options options;
+
 /*
  * Connect to the given ssh server using a proxy command.
  */
 int
-ssh_proxy_connect(const char *host, int port, uid_t original_real_uid,
+ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
 		  const char *proxy_command)
 {
 	Buffer command;
@@ -49,7 +51,7 @@
 	char portstring[100];
 
 	/* Convert the port number into a string. */
-	snprintf(portstring, sizeof portstring, "%d", port);
+	snprintf(portstring, sizeof portstring, "%hu", port);
 
 	/* Build the final command string in the buffer by making the
 	   appropriate substitutions to the given proxy command. */
@@ -177,7 +179,7 @@
  */
 int
 ssh_connect(const char *host, struct sockaddr_in * hostaddr,
-	    int port, int connection_attempts,
+	    u_short port, int connection_attempts,
 	    int anonymous, uid_t original_real_uid,
 	    const char *proxy_command)
 {
@@ -476,9 +478,8 @@
  * the user using it.
  */
 int
-try_rsa_authentication(struct passwd * pw, const char *authfile)
+try_rsa_authentication(const char *authfile)
 {
-	extern Options options;
 	BIGNUM *challenge;
 	RSA *private_key;
 	RSA *public_key;
@@ -490,7 +491,8 @@
 	public_key = RSA_new();
 	if (!load_public_key(authfile, public_key, &comment)) {
 		RSA_free(public_key);
-		return 0;	/* Could not load it.  Fail. */
+		/* Could not load it.  Fail. */
+		return 0;
 	}
 	debug("Trying RSA authentication with key '%.100s'", comment);
 
@@ -513,8 +515,7 @@
 	if (type == SSH_SMSG_FAILURE) {
 		debug("Server refused our key.");
 		xfree(comment);
-		return 0;	/* Server refuses to authenticate with
-				   this key. */
+		return 0;
 	}
 	/* Otherwise, the server should respond with a challenge. */
 	if (type != SSH_SMSG_AUTH_RSA_CHALLENGE)
@@ -885,6 +886,93 @@
 #endif /* AFS */
 
 /*
+ * Tries to authenticate with any string-based challenge/response system.
+ * Note that the client code is not tied to s/key or TIS.
+ */
+int
+try_skey_authentication()
+{
+	int type, i, payload_len;
+	char *challenge, *response;
+
+	debug("Doing skey authentication.");
+
+	/* request a challenge */
+	packet_start(SSH_CMSG_AUTH_TIS);
+	packet_send();
+	packet_write_wait();
+
+	type = packet_read(&payload_len);
+	if (type != SSH_SMSG_FAILURE &&
+	    type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
+		packet_disconnect("Protocol error: got %d in response "
+				  "to skey-auth", type);
+	}
+	if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
+		debug("No challenge for skey authentication.");
+		return 0;
+	}
+	challenge = packet_get_string(&payload_len);
+	if (options.cipher == SSH_CIPHER_NONE)
+		log("WARNING: Encryption is disabled! "
+		    "Reponse will be transmitted in clear text.");
+	fprintf(stderr, "%s\n", challenge);
+	fflush(stderr);
+	for (i = 0; i < options.number_of_password_prompts; i++) {
+		if (i != 0)
+			error("Permission denied, please try again.");
+		response = read_passphrase("Response: ", 0);
+		packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
+		packet_put_string(response, strlen(response));
+		memset(response, 0, strlen(response));
+		xfree(response);
+		packet_send();
+		packet_write_wait();
+		type = packet_read(&payload_len);
+		if (type == SSH_SMSG_SUCCESS)
+			return 1;
+		if (type != SSH_SMSG_FAILURE)
+			packet_disconnect("Protocol error: got %d in response "
+					  "to skey-auth-reponse", type);
+	}
+	/* failure */
+	return 0;
+}
+
+/*
+ * Tries to authenticate with plain passwd authentication.
+ */
+int
+try_password_authentication(char *prompt)
+{
+	int type, i, payload_len;
+	char *password;
+
+	debug("Doing password authentication.");
+	if (options.cipher == SSH_CIPHER_NONE)
+		log("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
+	for (i = 0; i < options.number_of_password_prompts; i++) {
+		if (i != 0)
+			error("Permission denied, please try again.");
+		password = read_passphrase(prompt, 0);
+		packet_start(SSH_CMSG_AUTH_PASSWORD);
+		packet_put_string(password, strlen(password));
+		memset(password, 0, strlen(password));
+		xfree(password);
+		packet_send();
+		packet_write_wait();
+
+		type = packet_read(&payload_len);
+		if (type == SSH_SMSG_SUCCESS)
+			return 1;
+		if (type != SSH_SMSG_FAILURE)
+			packet_disconnect("Protocol error: got %d in response to passwd auth", type);
+	}
+	/* failure */
+	return 0;
+}
+
+/*
  * Waits for the server identification string, and sends our own
  * identification string.
  */
@@ -895,7 +983,6 @@
 	int remote_major, remote_minor, i;
 	int connection_in = packet_get_connection_in();
 	int connection_out = packet_get_connection_out();
-	extern Options options;
 
 	/* Read other side\'s version identification. */
 	for (i = 0; i < sizeof(buf) - 1; i++) {
@@ -1015,9 +1102,7 @@
 	  struct sockaddr_in *hostaddr,
 	  uid_t original_real_uid)
 {
-	extern Options options;
 	int i, type;
-	char *password;
 	struct passwd *pw;
 	BIGNUM *key;
 	RSA *host_key, *file_key;
@@ -1036,6 +1121,13 @@
 	int payload_len, clen, sum_len = 0;
 	u_int32_t rand = 0;
 
+	/*
+	 * Turn off check_host_ip for proxy connects, since
+	 * we don't have the remote ip-address
+	 */
+	if (options.proxy_command != NULL && options.check_host_ip)
+		options.check_host_ip = 0;
+
 	if (options.check_host_ip)
 		ip = xstrdup(inet_ntoa(hostaddr->sin_addr));
 
@@ -1494,80 +1586,23 @@
 
 		/* Try RSA authentication for each identity. */
 		for (i = 0; i < options.num_identity_files; i++)
-			if (try_rsa_authentication(pw, options.identity_files[i]))
+			if (try_rsa_authentication(options.identity_files[i]))
 				return;
 	}
 	/* Try skey authentication if the server supports it. */
 	if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
 	    options.skey_authentication && !options.batch_mode) {
-		debug("Doing skey authentication.");
-
-		/* request a challenge */
-		packet_start(SSH_CMSG_AUTH_TIS);
-		packet_send();
-		packet_write_wait();
-
-		type = packet_read(&payload_len);
-		if (type != SSH_SMSG_FAILURE &&
-		    type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
-			packet_disconnect("Protocol error: got %d in response "
-					  "to skey auth", type);
-		}
-		if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
-			debug("No challenge for skey authentication.");
-		} else {
-			char *challenge, *response;
-			challenge = packet_get_string(&payload_len);
-			if (options.cipher == SSH_CIPHER_NONE)
-				log("WARNING: Encryption is disabled! "
-				    "Reponse will be transmitted in clear text.");
-			fprintf(stderr, "%s\n", challenge);
-			fflush(stderr);
-			for (i = 0; i < options.number_of_password_prompts; i++) {
-				if (i != 0)
-					error("Permission denied, please try again.");
-				response = read_passphrase("Response: ", 0);
-				packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
-				packet_put_string(response, strlen(response));
-				memset(response, 0, strlen(response));
-				xfree(response);
-				packet_send();
-				packet_write_wait();
-				type = packet_read(&payload_len);
-				if (type == SSH_SMSG_SUCCESS)
-					return;
-				if (type != SSH_SMSG_FAILURE)
-					packet_disconnect("Protocol error: got %d in response "
-						   	  "to skey auth", type);
-			}
-		}
+		if (try_skey_authentication())
+			return;
 	}
 	/* Try password authentication if the server supports it. */
 	if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
 	    options.password_authentication && !options.batch_mode) {
 		char prompt[80];
-		snprintf(prompt, sizeof(prompt), "%.30s@%.30s's password: ",
+		snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
 			 server_user, host);
-		debug("Doing password authentication.");
-		if (options.cipher == SSH_CIPHER_NONE)
-			log("WARNING: Encryption is disabled! Password will be transmitted in clear text.");
-		for (i = 0; i < options.number_of_password_prompts; i++) {
-			if (i != 0)
-				error("Permission denied, please try again.");
-			password = read_passphrase(prompt, 0);
-			packet_start(SSH_CMSG_AUTH_PASSWORD);
-			packet_put_string(password, strlen(password));
-			memset(password, 0, strlen(password));
-			xfree(password);
-			packet_send();
-			packet_write_wait();
-
-			type = packet_read(&payload_len);
-			if (type == SSH_SMSG_SUCCESS)
-				return;
-			if (type != SSH_SMSG_FAILURE)
-				packet_disconnect("Protocol error: got %d in response to passwd auth", type);
-		}
+		if (try_password_authentication(prompt))
+			return;
 	}
 	/* All authentication methods have failed.  Exit with an error message. */
 	fatal("Permission denied.");