- (djm) Merge BSD_AUTH support from Markus Friedl and David J. MacKenzie
   enable with --with-bsd-auth.
diff --git a/acconfig.h b/acconfig.h
index dc71608..d271534 100644
--- a/acconfig.h
+++ b/acconfig.h
@@ -1,4 +1,4 @@
-/* $Id: acconfig.h,v 1.101 2001/02/09 01:55:36 djm Exp $ */
+/* $Id: acconfig.h,v 1.102 2001/02/18 06:01:00 djm Exp $ */
 
 #ifndef _CONFIG_H
 #define _CONFIG_H
@@ -290,6 +290,9 @@
 /* Detect IPv4 in IPv6 mapped addresses and treat as IPv4 */
 #undef IPV4_IN_IPV6
 
+/* Define if you have BSD auth support */
+#undef BSD_AUTH
+
 @BOTTOM@
 
 /* ******************* Shouldn't need to edit below this line ************** */
diff --git a/auth-chall.c b/auth-chall.c
index b6ec02a..926c07e 100644
--- a/auth-chall.c
+++ b/auth-chall.c
@@ -26,7 +26,48 @@
 RCSID("$OpenBSD: auth-chall.c,v 1.4 2001/02/04 15:32:22 stevesk Exp $");
 
 #include "auth.h"
+#include "log.h"
 
+#ifdef BSD_AUTH
+char *
+get_challenge(Authctxt *authctxt, char *devs)
+{
+	char *challenge;
+
+	if (authctxt->as != NULL) {
+		debug2("try reuse session");
+		challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE);
+		if (challenge != NULL) {
+			debug2("reuse bsd auth session");
+			return challenge;
+		}
+		auth_close(authctxt->as);
+		authctxt->as = NULL;
+	}
+	debug2("new bsd auth session");
+	if (devs == NULL || strlen(devs) == 0)
+		devs = authctxt->style;
+	debug3("bsd auth: devs %s", devs ? devs : "<default>");
+	authctxt->as = auth_userchallenge(authctxt->user, devs, "auth-ssh",
+	    &challenge);
+        if (authctxt->as == NULL)
+                return NULL;
+	debug2("get_challenge: <%s>", challenge ? challenge : "EMPTY");
+	return challenge;
+}
+int
+verify_response(Authctxt *authctxt, char *response)
+{
+	int authok;
+
+	if (authctxt->as == 0)
+		error("verify_response: no bsd auth session");
+	authok = auth_userresponse(authctxt->as, response, 0);
+	authctxt->as = NULL;
+	debug("verify_response: <%s> = <%d>", response, authok);
+	return authok != 0;
+}
+#else
 #ifdef SKEY
 #include <skey.h>
 
@@ -60,3 +101,4 @@
 	return 0;
 }
 #endif
+#endif
diff --git a/auth-passwd.c b/auth-passwd.c
index c849abd..5a91e55 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -77,14 +77,17 @@
 #define is_winnt       (GetVersion() < 0x80000000)
 #endif
 
+
+extern ServerOptions options;
+
 /*
  * Tries to authenticate the user using password.  Returns true if
  * authentication succeeds.
  */
 int
-auth_password(struct passwd * pw, const char *password)
+auth_password(Authctxt *authctxt, const char *password)
 {
-	extern ServerOptions options;
+	struct passwd * pw = authctxt->pw;
 	char *encrypted_password;
 	char *pw_password;
 	char *salt;
@@ -122,6 +125,13 @@
 #endif
 	if (*password == '\0' && options.permit_empty_passwd == 0)
 		return 0;
+#ifdef BSD_AUTH
+	if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh",
+	    (char *)password) == 0)
+		return 0;
+	else
+		return 1;
+#endif
 
 #ifdef HAVE_CYGWIN
 	if (is_winnt) {
diff --git a/auth.h b/auth.h
index 0684f6f..4575533 100644
--- a/auth.h
+++ b/auth.h
@@ -28,6 +28,13 @@
 
 #include <openssl/rsa.h>
 
+#ifdef HAVE_LOGIN_CAP
+#include <login_cap.h>
+#endif
+#ifdef BSD_AUTH
+#include <bsd_auth.h>
+#endif
+
 typedef struct Authctxt Authctxt;
 struct Authctxt {
 	int success;
@@ -39,6 +46,9 @@
 	char *service;
 	struct passwd *pw;
 	char *style;
+#ifdef BSD_AUTH
+	auth_session_t *as;
+#endif
 };
 
 /*
@@ -59,7 +69,7 @@
  * Tries to authenticate the user using password.  Returns true if
  * authentication succeeds.
  */
-int     auth_password(struct passwd * pw, const char *password);
+int     auth_password(Authctxt *authctxt, const char *password);
 
 /*
  * Performs the RSA authentication dialog with the client.  This returns 0 if
diff --git a/auth1.c b/auth1.c
index 11c56a5..beccf2b 100644
--- a/auth1.c
+++ b/auth1.c
@@ -92,7 +92,7 @@
 #elif defined(HAVE_OSF_SIA)
 	    0) {
 #else
-	    auth_password(pw, "")) {
+	    auth_password(authctxt, "")) {
 #endif
 		auth_log(authctxt, 1, "without authentication", "");
 		return;
@@ -262,7 +262,7 @@
 			    password);
 #else /* !USE_PAM && !HAVE_OSF_SIA */
 			/* Try authentication with the password. */
-			authenticated = auth_password(pw, password);
+			authenticated = auth_password(authctxt, password);
 #endif /* USE_PAM */
 
 			memset(password, 0, strlen(password));
@@ -303,6 +303,12 @@
 			log("Unknown message during authentication: type %d", type);
 			break;
 		}
+#ifdef BSD_AUTH
+		if (authctxt->as) {
+			auth_close(authctxt->as);
+			authctxt->as = NULL;
+		}
+#endif
 		if (!authctxt->valid && authenticated)
 			fatal("INTERNAL ERROR: authenticated invalid user %s",
 			    authctxt->user);
diff --git a/auth2.c b/auth2.c
index 88fca2c..cd3886d 100644
--- a/auth2.c
+++ b/auth2.c
@@ -218,6 +218,12 @@
 	/* reset state */
 	dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &protocol_error);
 	authctxt->postponed = 0;
+#ifdef BSD_AUTH
+	if (authctxt->as) {
+		auth_close(authctxt->as);
+		authctxt->as = NULL;
+	}
+#endif
 
 	/* try to authenticate user */
 	m = authmethod_lookup(method);
@@ -341,7 +347,7 @@
 #elif defined(HAVE_OSF_SIA)
 	return 0;
 #else /* !HAVE_OSF_SIA && !USE_PAM */
-	return auth_password(authctxt->pw, "");
+	return auth_password(authctxt, "");
 #endif /* USE_PAM */
 }
 
@@ -366,7 +372,7 @@
 #elif defined(HAVE_OSF_SIA)
 	    auth_sia_password(authctxt->user, password) == 1)
 #else /* !USE_PAM && !HAVE_OSF_SIA */
-	    auth_password(authctxt->pw, password) == 1)
+	    auth_password(authctxt, password) == 1)
 #endif /* USE_PAM */
 		authenticated = 1;
 	memset(password, 0, len);
diff --git a/configure.in b/configure.in
index cbc866a..a5870f3 100644
--- a/configure.in
+++ b/configure.in
@@ -1,4 +1,4 @@
-# $Id: configure.in,v 1.246 2001/02/18 04:29:29 djm Exp $
+# $Id: configure.in,v 1.247 2001/02/18 06:01:00 djm Exp $
 
 AC_INIT(ssh.c)
 
@@ -1411,6 +1411,17 @@
 	]
 )
 
+# Whether to enable BSD auth support
+AC_ARG_WITH(bsd-auth,
+	[  --with-bsd-auth         Enable BSD auth support],
+	[
+		if test "x$withval" != "xno" ; then	
+			AC_DEFINE(BSD_AUTH)
+			bsd_auth=yes
+		fi
+	]
+)
+
 AC_MSG_CHECKING(whether to install ssh as suid root)
 AC_ARG_ENABLE(suid-ssh,
 [  --enable-suid-ssh       Install ssh as suid root (default)
@@ -1739,6 +1750,10 @@
 echo "      Use IPv4 by default hack: $IPV4_HACK_MSG"
 echo "       Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
 
+if test ! -z "$bsd_auth"; then
+	echo "              BSD Auth support: yes"
+fi
+
 echo ""
 
 echo "              Host: ${host}"
@@ -1769,3 +1784,4 @@
 	echo "64bit integers."
 	echo ""
 fi
+
diff --git a/session.c b/session.c
index 4e2471f..b84f19e 100644
--- a/session.c
+++ b/session.c
@@ -89,10 +89,6 @@
 # define S_UNOFILE_HARD	S_UNOFILE "_hard"
 #endif
 
-#ifdef HAVE_LOGIN_CAP
-#include <login_cap.h>
-#endif
-
 /* types */
 
 #define TTYSZ 64
@@ -1071,6 +1067,13 @@
 				perror("unable to set user context");
 				exit(1);
 			}
+#ifdef BSD_AUTH
+			if (auth_approval(NULL, lc, pw->pw_name, "ssh") <= 0) {
+				error("approval failure for %s", pw->pw_name);
+				fprintf(stderr, "Approval failure");
+				exit(1);
+			}
+#endif
 # else /* HAVE_LOGIN_CAP */
 			if (setlogin(pw->pw_name) < 0)
 				error("setlogin failed: %s", strerror(errno));