- markus@cvs.openbsd.org 2002/05/25 18:51:07
     [auth.h auth2.c auth2-hostbased.c auth2-kbdint.c auth2-none.c
      auth2-passwd.c auth2-pubkey.c Makefile.in]
     split auth2.c into one file per method; ok provos@/deraadt@

NOTE: Merged back noticable cygwin and pam stuff.  May need review to
ensure I did not miss anything.
diff --git a/ChangeLog b/ChangeLog
index f43d192..38ea644 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -31,6 +31,10 @@
    - markus@cvs.openbsd.org 2002/05/25 08:50:39
      [sshconnect2.c]
      execlp->execl; from stevesk
+   - markus@cvs.openbsd.org 2002/05/25 18:51:07
+     [auth.h auth2.c auth2-hostbased.c auth2-kbdint.c auth2-none.c
+      auth2-passwd.c auth2-pubkey.c Makefile.in]
+     split auth2.c into one file per method; ok provos@/deraadt@
 
 20020604
  - (stevesk) [channels.c] bug #164 patch from YOSHIFUJI Hideaki (changed
@@ -715,4 +719,4 @@
  - (stevesk) entropy.c: typo in debug message
  - (djm) ssh-keygen -i needs seeded RNG; report from markus@
 
-$Id: ChangeLog,v 1.2152 2002/06/06 20:05:57 mouring Exp $
+$Id: ChangeLog,v 1.2153 2002/06/06 20:27:55 mouring Exp $
diff --git a/Makefile.in b/Makefile.in
index ec235f8..4001d68 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
-# $Id: Makefile.in,v 1.209 2002/06/06 19:57:33 mouring Exp $
+# $Id: Makefile.in,v 1.210 2002/06/06 20:27:55 mouring Exp $
 
 # uncomment if you run a non bourne compatable shell. Ie. csh
 #SHELL = @SH@
@@ -61,7 +61,7 @@
 
 SSHOBJS= ssh.o sshconnect.o sshconnect1.o sshconnect2.o sshtty.o readconf.o clientloop.o
 
-SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.o auth-krb5.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o auth-sia.o sshpty.o sshlogin.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o auth-skey.o auth-bsdauth.o monitor_mm.o monitor.o
+SSHDOBJS= sshd.o auth.o auth1.o auth2.o auth2-hostbased.o auth2-kbdint.o auth2-none.o auth2-passwd.o auth2-pubkey.o auth-chall.o auth2-chall.o auth-rhosts.o auth-options.o auth-krb4.o auth-krb5.o auth-pam.o auth2-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o auth-sia.o sshpty.o sshlogin.o loginrec.o servconf.o serverloop.o md5crypt.o session.o groupaccess.o auth-skey.o auth-bsdauth.o monitor_mm.o monitor.o
 
 MANPAGES	= scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-rand-helper.8.out
 MANPAGES_IN	= scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-rand-helper.8
diff --git a/auth.h b/auth.h
index 2211c5b..59646eb 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: auth.h,v 1.37 2002/05/13 20:44:58 markus Exp $	*/
+/*	$OpenBSD: auth.h,v 1.38 2002/05/25 18:51:07 markus Exp $	*/
 
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
@@ -100,6 +100,13 @@
 int	 auth_rsa_verify_response(Key *, BIGNUM *, u_char[]);
 int	 auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
 
+/* ssh2 methods */
+int	 userauth_none(Authctxt *);
+int	 userauth_passwd(Authctxt *);
+int	 userauth_pubkey(Authctxt *);
+int	 userauth_hostbased(Authctxt *);
+int	 userauth_kbdint(Authctxt *);
+
 int	 auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
 int	 hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
 int	 user_key_allowed(struct passwd *, Key *);
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
new file mode 100644
index 0000000..2bde7bb
--- /dev/null
+++ b/auth2-hostbased.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-hostbased.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
+
+#include "ssh2.h"
+#include "xmalloc.h"
+#include "packet.h"
+#include "buffer.h"
+#include "log.h"
+#include "servconf.h"
+#include "compat.h"
+#include "bufaux.h"
+#include "auth.h"
+#include "key.h"
+#include "canohost.h"
+#include "monitor_wrap.h"
+#include "pathnames.h"
+
+/* import */
+extern ServerOptions options;
+extern u_char *session_id2;
+extern int session_id2_len;
+
+static int
+userauth_hostbased(Authctxt *authctxt)
+{
+	Buffer b;
+	Key *key = NULL;
+	char *pkalg, *cuser, *chost, *service;
+	u_char *pkblob, *sig;
+	u_int alen, blen, slen;
+	int pktype;
+	int authenticated = 0;
+
+	if (!authctxt->valid) {
+		debug2("userauth_hostbased: disabled because of invalid user");
+		return 0;
+	}
+	pkalg = packet_get_string(&alen);
+	pkblob = packet_get_string(&blen);
+	chost = packet_get_string(NULL);
+	cuser = packet_get_string(NULL);
+	sig = packet_get_string(&slen);
+
+	debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
+	    cuser, chost, pkalg, slen);
+#ifdef DEBUG_PK
+	debug("signature:");
+	buffer_init(&b);
+	buffer_append(&b, sig, slen);
+	buffer_dump(&b);
+	buffer_free(&b);
+#endif
+	pktype = key_type_from_name(pkalg);
+	if (pktype == KEY_UNSPEC) {
+		/* this is perfectly legal */
+		log("userauth_hostbased: unsupported "
+		    "public key algorithm: %s", pkalg);
+		goto done;
+	}
+	key = key_from_blob(pkblob, blen);
+	if (key == NULL) {
+		error("userauth_hostbased: cannot decode key: %s", pkalg);
+		goto done;
+	}
+	if (key->type != pktype) {
+		error("userauth_hostbased: type mismatch for decoded key "
+		    "(received %d, expected %d)", key->type, pktype);
+		goto done;
+	}
+	service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
+	    authctxt->service;
+	buffer_init(&b);
+	buffer_put_string(&b, session_id2, session_id2_len);
+	/* reconstruct packet */
+	buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+	buffer_put_cstring(&b, authctxt->user);
+	buffer_put_cstring(&b, service);
+	buffer_put_cstring(&b, "hostbased");
+	buffer_put_string(&b, pkalg, alen);
+	buffer_put_string(&b, pkblob, blen);
+	buffer_put_cstring(&b, chost);
+	buffer_put_cstring(&b, cuser);
+#ifdef DEBUG_PK
+	buffer_dump(&b);
+#endif
+	/* test for allowed key and correct signature */
+	authenticated = 0;
+	if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) &&
+	    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+			buffer_len(&b))) == 1)
+		authenticated = 1;
+
+	buffer_clear(&b);
+done:
+	debug2("userauth_hostbased: authenticated %d", authenticated);
+	if (key != NULL)
+		key_free(key);
+	xfree(pkalg);
+	xfree(pkblob);
+	xfree(cuser);
+	xfree(chost);
+	xfree(sig);
+	return authenticated;
+}
+
+/* return 1 if given hostkey is allowed */
+int
+hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
+    Key *key)
+{
+	const char *resolvedname, *ipaddr, *lookup;
+	HostStatus host_status;
+	int len;
+
+	resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
+	ipaddr = get_remote_ipaddr();
+
+	debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
+	    chost, resolvedname, ipaddr);
+
+	if (options.hostbased_uses_name_from_packet_only) {
+		if (auth_rhosts2(pw, cuser, chost, chost) == 0)
+			return 0;
+		lookup = chost;
+	} else {
+		if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
+			debug2("stripping trailing dot from chost %s", chost);
+			chost[len - 1] = '\0';
+		}
+		if (strcasecmp(resolvedname, chost) != 0)
+			log("userauth_hostbased mismatch: "
+			    "client sends %s, but we resolve %s to %s",
+			    chost, ipaddr, resolvedname);
+		if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
+			return 0;
+		lookup = resolvedname;
+	}
+	debug2("userauth_hostbased: access allowed by auth_rhosts2");
+
+	host_status = check_key_in_hostfiles(pw, key, lookup,
+	    _PATH_SSH_SYSTEM_HOSTFILE,
+	    options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
+
+	/* backward compat if no key has been found. */
+	if (host_status == HOST_NEW)
+		host_status = check_key_in_hostfiles(pw, key, lookup,
+		    _PATH_SSH_SYSTEM_HOSTFILE2,
+		    options.ignore_user_known_hosts ? NULL :
+		    _PATH_SSH_USER_HOSTFILE2);
+
+	return (host_status == HOST_OK);
+}
+
+Authmethod method_hostbased = {
+	"hostbased",
+	userauth_hostbased,
+	&options.hostbased_authentication
+};
diff --git a/auth2-kbdint.c b/auth2-kbdint.c
new file mode 100644
index 0000000..e609928
--- /dev/null
+++ b/auth2-kbdint.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-kbdint.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
+
+#include "packet.h"
+#include "auth.h"
+#include "log.h"
+#include "servconf.h"
+#include "xmalloc.h"
+
+/* import */
+extern ServerOptions options;
+
+static int
+userauth_kbdint(Authctxt *authctxt)
+{
+	int authenticated = 0;
+	char *lang, *devs;
+
+	lang = packet_get_string(NULL);
+	devs = packet_get_string(NULL);
+	packet_check_eom();
+
+	debug("keyboard-interactive devs %s", devs);
+
+	if (options.challenge_response_authentication)
+		authenticated = auth2_challenge(authctxt, devs);
+
+#ifdef USE_PAM
+	if (authenticated == 0 && options.pam_authentication_via_kbd_int)
+		authenticated = auth2_pam(authctxt);
+#endif
+	xfree(devs);
+	xfree(lang);
+#ifdef HAVE_CYGWIN
+	if (check_nt_auth(0, authctxt->pw) == 0)
+		return(0);
+#endif
+	return authenticated;
+}
+
+Authmethod method_kbdint = {
+	"keyboard-interactive",
+	userauth_kbdint,
+	&options.kbd_interactive_authentication
+};
diff --git a/auth2-none.c b/auth2-none.c
new file mode 100644
index 0000000..30337fd
--- /dev/null
+++ b/auth2-none.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-none.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
+
+#include "auth.h"
+#include "xmalloc.h"
+#include "packet.h"
+#include "log.h"
+#include "servconf.h"
+#include "atomicio.h"
+#include "compat.h"
+#include "ssh2.h"
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
+
+/* "none" is allowed only one time */
+static int none_enabled = 1;
+
+char *
+auth2_read_banner(void)
+{
+	struct stat st;
+	char *banner = NULL;
+	off_t len, n;
+	int fd;
+
+	if ((fd = open(options.banner, O_RDONLY)) == -1)
+		return (NULL);
+	if (fstat(fd, &st) == -1) {
+		close(fd);
+		return (NULL);
+	}
+	len = st.st_size;
+	banner = xmalloc(len + 1);
+	n = atomicio(read, fd, banner, len);
+	close(fd);
+
+	if (n != len) {
+		free(banner);
+		return (NULL);
+	}
+	banner[n] = '\0';
+	
+	return (banner);
+}
+
+static void
+userauth_banner(void)
+{
+	char *banner = NULL;
+
+	if (options.banner == NULL || (datafellows & SSH_BUG_BANNER))
+		return;
+
+	if ((banner = PRIVSEP(auth2_read_banner())) == NULL)
+		goto done;
+
+	packet_start(SSH2_MSG_USERAUTH_BANNER);
+	packet_put_cstring(banner);
+	packet_put_cstring("");		/* language, unused */
+	packet_send();
+	debug("userauth_banner: sent");
+done:
+	if (banner)
+		xfree(banner);
+	return;
+}
+
+static int
+userauth_none(Authctxt *authctxt)
+{
+	none_enabled = 0;
+	packet_check_eom();
+	userauth_banner();
+#ifdef HAVE_CYGWIN
+	if (check_nt_auth(1, authctxt->pw) == 0)
+		return(0);
+#endif
+	return (authctxt->valid ? PRIVSEP(auth_password(authctxt, "")) : 0);
+}
+
+Authmethod method_none = {
+	"none",
+	userauth_none,
+	&none_enabled
+};
diff --git a/auth2-passwd.c b/auth2-passwd.c
new file mode 100644
index 0000000..ffa2795
--- /dev/null
+++ b/auth2-passwd.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-passwd.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
+
+#include "xmalloc.h"
+#include "packet.h"
+#include "log.h"
+#include "auth.h"
+#include "monitor_wrap.h"
+#include "servconf.h"
+
+/* import */
+extern ServerOptions options;
+
+static int
+userauth_passwd(Authctxt *authctxt)
+{
+	char *password;
+	int authenticated = 0;
+	int change;
+	u_int len;
+	change = packet_get_char();
+	if (change)
+		log("password change not supported");
+	password = packet_get_string(&len);
+	packet_check_eom();
+	if (authctxt->valid &&
+#ifdef HAVE_CYGWIN
+	    check_nt_auth(1, authctxt->pw) &&
+#endif
+	    PRIVSEP(auth_password(authctxt, password)) == 1)
+		authenticated = 1;
+	memset(password, 0, len);
+	xfree(password);
+	return authenticated;
+}
+
+Authmethod method_passwd = {
+	"password",
+	userauth_passwd,
+	&options.password_authentication
+};
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
new file mode 100644
index 0000000..947bfed
--- /dev/null
+++ b/auth2-pubkey.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2000 Markus Friedl.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "includes.h"
+RCSID("$OpenBSD: auth2-pubkey.c,v 1.2 2002/05/31 11:35:15 markus Exp $");
+
+#include "ssh2.h"
+#include "xmalloc.h"
+#include "packet.h"
+#include "buffer.h"
+#include "log.h"
+#include "servconf.h"
+#include "compat.h"
+#include "bufaux.h"
+#include "auth.h"
+#include "key.h"
+#include "pathnames.h"
+#include "uidswap.h"
+#include "auth-options.h"
+#include "canohost.h"
+#include "monitor_wrap.h"
+
+/* import */
+extern ServerOptions options;
+extern u_char *session_id2;
+extern int session_id2_len;
+
+static int
+userauth_pubkey(Authctxt *authctxt)
+{
+	Buffer b;
+	Key *key = NULL;
+	char *pkalg;
+	u_char *pkblob, *sig;
+	u_int alen, blen, slen;
+	int have_sig, pktype;
+	int authenticated = 0;
+
+	if (!authctxt->valid) {
+		debug2("userauth_pubkey: disabled because of invalid user");
+		return 0;
+	}
+	have_sig = packet_get_char();
+	if (datafellows & SSH_BUG_PKAUTH) {
+		debug2("userauth_pubkey: SSH_BUG_PKAUTH");
+		/* no explicit pkalg given */
+		pkblob = packet_get_string(&blen);
+		buffer_init(&b);
+		buffer_append(&b, pkblob, blen);
+		/* so we have to extract the pkalg from the pkblob */
+		pkalg = buffer_get_string(&b, &alen);
+		buffer_free(&b);
+	} else {
+		pkalg = packet_get_string(&alen);
+		pkblob = packet_get_string(&blen);
+	}
+	pktype = key_type_from_name(pkalg);
+	if (pktype == KEY_UNSPEC) {
+		/* this is perfectly legal */
+		log("userauth_pubkey: unsupported public key algorithm: %s",
+		    pkalg);
+		goto done;
+	}
+	key = key_from_blob(pkblob, blen);
+	if (key == NULL) {
+		error("userauth_pubkey: cannot decode key: %s", pkalg);
+		goto done;
+	}
+	if (key->type != pktype) {
+		error("userauth_pubkey: type mismatch for decoded key "
+		    "(received %d, expected %d)", key->type, pktype);
+		goto done;
+	}
+	if (have_sig) {
+		sig = packet_get_string(&slen);
+		packet_check_eom();
+		buffer_init(&b);
+		if (datafellows & SSH_OLD_SESSIONID) {
+			buffer_append(&b, session_id2, session_id2_len);
+		} else {
+			buffer_put_string(&b, session_id2, session_id2_len);
+		}
+		/* reconstruct packet */
+		buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
+		buffer_put_cstring(&b, authctxt->user);
+		buffer_put_cstring(&b,
+		    datafellows & SSH_BUG_PKSERVICE ?
+		    "ssh-userauth" :
+		    authctxt->service);
+		if (datafellows & SSH_BUG_PKAUTH) {
+			buffer_put_char(&b, have_sig);
+		} else {
+			buffer_put_cstring(&b, "publickey");
+			buffer_put_char(&b, have_sig);
+			buffer_put_cstring(&b, pkalg);
+		}
+		buffer_put_string(&b, pkblob, blen);
+#ifdef DEBUG_PK
+		buffer_dump(&b);
+#endif
+		/* test for correct signature */
+		authenticated = 0;
+		if (PRIVSEP(user_key_allowed(authctxt->pw, key)) &&
+		    PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),
+				buffer_len(&b))) == 1)
+			authenticated = 1;
+		buffer_clear(&b);
+		xfree(sig);
+	} else {
+		debug("test whether pkalg/pkblob are acceptable");
+		packet_check_eom();
+
+		/* XXX fake reply and always send PK_OK ? */
+		/*
+		 * XXX this allows testing whether a user is allowed
+		 * to login: if you happen to have a valid pubkey this
+		 * message is sent. the message is NEVER sent at all
+		 * if a user is not allowed to login. is this an
+		 * issue? -markus
+		 */
+		if (PRIVSEP(user_key_allowed(authctxt->pw, key))) {
+			packet_start(SSH2_MSG_USERAUTH_PK_OK);
+			packet_put_string(pkalg, alen);
+			packet_put_string(pkblob, blen);
+			packet_send();
+			packet_write_wait();
+			authctxt->postponed = 1;
+		}
+	}
+	if (authenticated != 1)
+		auth_clear_options();
+done:
+	debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
+	if (key != NULL)
+		key_free(key);
+	xfree(pkalg);
+	xfree(pkblob);
+#ifdef HAVE_CYGWIN
+	if (check_nt_auth(0, authctxt->pw) == 0)
+		return(0);
+#endif
+	return authenticated;
+}
+
+/* return 1 if user allows given key */
+static int
+user_key_allowed2(struct passwd *pw, Key *key, char *file)
+{
+	char line[8192];
+	int found_key = 0;
+	FILE *f;
+	u_long linenum = 0;
+	struct stat st;
+	Key *found;
+	char *fp;
+
+	if (pw == NULL)
+		return 0;
+
+	/* Temporarily use the user's uid. */
+	temporarily_use_uid(pw);
+
+	debug("trying public key file %s", file);
+
+	/* Fail quietly if file does not exist */
+	if (stat(file, &st) < 0) {
+		/* Restore the privileged uid. */
+		restore_uid();
+		return 0;
+	}
+	/* Open the file containing the authorized keys. */
+	f = fopen(file, "r");
+	if (!f) {
+		/* Restore the privileged uid. */
+		restore_uid();
+		return 0;
+	}
+	if (options.strict_modes &&
+	    secure_filename(f, file, pw, line, sizeof(line)) != 0) {
+		fclose(f);
+		log("Authentication refused: %s", line);
+		restore_uid();
+		return 0;
+	}
+
+	found_key = 0;
+	found = key_new(key->type);
+
+	while (fgets(line, sizeof(line), f)) {
+		char *cp, *options = NULL;
+		linenum++;
+		/* Skip leading whitespace, empty and comment lines. */
+		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
+			;
+		if (!*cp || *cp == '\n' || *cp == '#')
+			continue;
+
+		if (key_read(found, &cp) != 1) {
+			/* no key?  check if there are options for this key */
+			int quoted = 0;
+			debug2("user_key_allowed: check options: '%s'", cp);
+			options = cp;
+			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
+				if (*cp == '\\' && cp[1] == '"')
+					cp++;	/* Skip both */
+				else if (*cp == '"')
+					quoted = !quoted;
+			}
+			/* Skip remaining whitespace. */
+			for (; *cp == ' ' || *cp == '\t'; cp++)
+				;
+			if (key_read(found, &cp) != 1) {
+				debug2("user_key_allowed: advance: '%s'", cp);
+				/* still no key?  advance to next line*/
+				continue;
+			}
+		}
+		if (key_equal(found, key) &&
+		    auth_parse_options(pw, options, file, linenum) == 1) {
+			found_key = 1;
+			debug("matching key found: file %s, line %lu",
+			    file, linenum);
+			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
+			verbose("Found matching %s key: %s",
+			    key_type(found), fp);
+			xfree(fp);
+			break;
+		}
+	}
+	restore_uid();
+	fclose(f);
+	key_free(found);
+	if (!found_key)
+		debug2("key not found");
+	return found_key;
+}
+
+/* check whether given key is in .ssh/authorized_keys* */
+int
+user_key_allowed(struct passwd *pw, Key *key)
+{
+	int success;
+	char *file;
+
+	file = authorized_keys_file(pw);
+	success = user_key_allowed2(pw, key, file);
+	xfree(file);
+	if (success)
+		return success;
+
+	/* try suffix "2" for backward compat, too */
+	file = authorized_keys_file2(pw);
+	success = user_key_allowed2(pw, key, file);
+	xfree(file);
+	return success;
+}
+
+Authmethod method_pubkey = {
+	"publickey",
+	userauth_pubkey,
+	&options.pubkey_authentication
+};
diff --git a/auth2.c b/auth2.c
index 6bcc565..ffd7032 100644
--- a/auth2.c
+++ b/auth2.c
@@ -23,35 +23,18 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.91 2002/05/13 02:37:39 itojun Exp $");
-
-#include <openssl/evp.h>
+RCSID("$OpenBSD: auth2.c,v 1.92 2002/05/25 18:51:07 markus Exp $");
 
 #include "ssh2.h"
 #include "xmalloc.h"
-#include "rsa.h"
-#include "sshpty.h"
 #include "packet.h"
-#include "buffer.h"
 #include "log.h"
 #include "servconf.h"
 #include "compat.h"
-#include "channels.h"
-#include "bufaux.h"
 #include "auth.h"
-#include "session.h"
 #include "dispatch.h"
-#include "key.h"
-#include "cipher.h"
-#include "kex.h"
 #include "pathnames.h"
-#include "uidswap.h"
-#include "auth-options.h"
-#include "hostfile.h"
-#include "canohost.h"
-#include "match.h"
 #include "monitor_wrap.h"
-#include "atomicio.h"
 
 /* import */
 extern ServerOptions options;
@@ -80,12 +63,6 @@
 int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
 
 /* auth */
-static void userauth_banner(void);
-static int userauth_none(Authctxt *);
-static int userauth_passwd(Authctxt *);
-static int userauth_pubkey(Authctxt *);
-static int userauth_hostbased(Authctxt *);
-static int userauth_kbdint(Authctxt *);
 
 Authmethod authmethods[] = {
 	{"none",
@@ -651,164 +628,3 @@
 	debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
 	return NULL;
 }
-
-/* return 1 if user allows given key */
-static int
-user_key_allowed2(struct passwd *pw, Key *key, char *file)
-{
-	char line[8192];
-	int found_key = 0;
-	FILE *f;
-	u_long linenum = 0;
-	struct stat st;
-	Key *found;
-	char *fp;
-
-	if (pw == NULL)
-		return 0;
-
-	/* Temporarily use the user's uid. */
-	temporarily_use_uid(pw);
-
-	debug("trying public key file %s", file);
-
-	/* Fail quietly if file does not exist */
-	if (stat(file, &st) < 0) {
-		/* Restore the privileged uid. */
-		restore_uid();
-		return 0;
-	}
-	/* Open the file containing the authorized keys. */
-	f = fopen(file, "r");
-	if (!f) {
-		/* Restore the privileged uid. */
-		restore_uid();
-		return 0;
-	}
-	if (options.strict_modes &&
-	    secure_filename(f, file, pw, line, sizeof(line)) != 0) {
-		fclose(f);
-		log("Authentication refused: %s", line);
-		restore_uid();
-		return 0;
-	}
-
-	found_key = 0;
-	found = key_new(key->type);
-
-	while (fgets(line, sizeof(line), f)) {
-		char *cp, *options = NULL;
-		linenum++;
-		/* Skip leading whitespace, empty and comment lines. */
-		for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
-			;
-		if (!*cp || *cp == '\n' || *cp == '#')
-			continue;
-
-		if (key_read(found, &cp) != 1) {
-			/* no key?  check if there are options for this key */
-			int quoted = 0;
-			debug2("user_key_allowed: check options: '%s'", cp);
-			options = cp;
-			for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
-				if (*cp == '\\' && cp[1] == '"')
-					cp++;	/* Skip both */
-				else if (*cp == '"')
-					quoted = !quoted;
-			}
-			/* Skip remaining whitespace. */
-			for (; *cp == ' ' || *cp == '\t'; cp++)
-				;
-			if (key_read(found, &cp) != 1) {
-				debug2("user_key_allowed: advance: '%s'", cp);
-				/* still no key?  advance to next line*/
-				continue;
-			}
-		}
-		if (key_equal(found, key) &&
-		    auth_parse_options(pw, options, file, linenum) == 1) {
-			found_key = 1;
-			debug("matching key found: file %s, line %lu",
-			    file, linenum);
-			fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
-			verbose("Found matching %s key: %s",
-			    key_type(found), fp);
-			xfree(fp);
-			break;
-		}
-	}
-	restore_uid();
-	fclose(f);
-	key_free(found);
-	if (!found_key)
-		debug2("key not found");
-	return found_key;
-}
-
-/* check whether given key is in .ssh/authorized_keys* */
-int
-user_key_allowed(struct passwd *pw, Key *key)
-{
-	int success;
-	char *file;
-
-	file = authorized_keys_file(pw);
-	success = user_key_allowed2(pw, key, file);
-	xfree(file);
-	if (success)
-		return success;
-
-	/* try suffix "2" for backward compat, too */
-	file = authorized_keys_file2(pw);
-	success = user_key_allowed2(pw, key, file);
-	xfree(file);
-	return success;
-}
-
-/* return 1 if given hostkey is allowed */
-int
-hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
-    Key *key)
-{
-	const char *resolvedname, *ipaddr, *lookup;
-	HostStatus host_status;
-	int len;
-
-	resolvedname = get_canonical_hostname(options.verify_reverse_mapping);
-	ipaddr = get_remote_ipaddr();
-
-	debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
-	    chost, resolvedname, ipaddr);
-
-	if (options.hostbased_uses_name_from_packet_only) {
-		if (auth_rhosts2(pw, cuser, chost, chost) == 0)
-			return 0;
-		lookup = chost;
-	} else {
-		if (((len = strlen(chost)) > 0) && chost[len - 1] == '.') {
-			debug2("stripping trailing dot from chost %s", chost);
-			chost[len - 1] = '\0';
-		}
-		if (strcasecmp(resolvedname, chost) != 0)
-			log("userauth_hostbased mismatch: "
-			    "client sends %s, but we resolve %s to %s",
-			    chost, ipaddr, resolvedname);
-		if (auth_rhosts2(pw, cuser, resolvedname, ipaddr) == 0)
-			return 0;
-		lookup = resolvedname;
-	}
-	debug2("userauth_hostbased: access allowed by auth_rhosts2");
-
-	host_status = check_key_in_hostfiles(pw, key, lookup,
-	    _PATH_SSH_SYSTEM_HOSTFILE,
-	    options.ignore_user_known_hosts ? NULL : _PATH_SSH_USER_HOSTFILE);
-
-	/* backward compat if no key has been found. */
-	if (host_status == HOST_NEW)
-		host_status = check_key_in_hostfiles(pw, key, lookup,
-		    _PATH_SSH_SYSTEM_HOSTFILE2,
-		    options.ignore_user_known_hosts ? NULL :
-		    _PATH_SSH_USER_HOSTFILE2);
-
-	return (host_status == HOST_OK);
-}