upstream: switch over to the new authorized_keys options API and

remove the legacy one.

Includes a fairly big refactor of auth2-pubkey.c to retain less state
between key file lines.

feedback and ok markus@

OpenBSD-Commit-ID: dece6cae0f47751b9892080eb13d6625599573df
diff --git a/monitor.c b/monitor.c
index e4ac3cc..c68e1b0 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.179 2018/02/05 05:37:46 tb Exp $ */
+/* $OpenBSD: monitor.c,v 1.180 2018/03/03 03:15:51 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -116,6 +116,7 @@
 extern Buffer auth_debug;
 extern int auth_debug_init;
 extern Buffer loginmsg;
+extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */
 
 /* State exported from the child */
 static struct sshbuf *child_state;
@@ -172,6 +173,7 @@
 static u_char *key_blob = NULL;
 static u_int key_bloblen = 0;
 static int key_blobtype = MM_NOKEY;
+static struct sshauthopt *key_opts = NULL;
 static char *hostbased_cuser = NULL;
 static char *hostbased_chost = NULL;
 static char *auth_method = "unknown";
@@ -252,7 +254,6 @@
 struct mon_table *mon_dispatch;
 
 /* Specifies if a certain message is allowed at the moment */
-
 static void
 monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
 {
@@ -297,6 +298,7 @@
 
 	authctxt = _authctxt;
 	memset(authctxt, 0, sizeof(*authctxt));
+	ssh->authctxt = authctxt;
 
 	authctxt->loginmsg = &loginmsg;
 
@@ -331,7 +333,7 @@
 				fatal("%s: unexpected authentication from %d",
 				    __func__, ent->type);
 			if (authctxt->pw->pw_uid == 0 &&
-			    !auth_root_allowed(auth_method))
+			    !auth_root_allowed(ssh, auth_method))
 				authenticated = 0;
 #ifdef USE_PAM
 			/* PAM needs to perform account checks after auth */
@@ -365,6 +367,7 @@
 
 	debug("%s: %s has been authenticated by privileged process",
 	    __func__, authctxt->user);
+	ssh->authctxt = NULL;
 	ssh_packet_set_log_preamble(ssh, "user %s", authctxt->user);
 
 	mm_get_keystate(pmonitor);
@@ -413,7 +416,7 @@
 	monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
 	monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
 
-	if (!no_pty_flag) {
+	if (auth_opts->permit_pty_flag) {
 		monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
 		monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
 	}
@@ -558,9 +561,11 @@
 	free(key_blob);
 	free(hostbased_cuser);
 	free(hostbased_chost);
+	sshauthopt_free(key_opts);
 	key_blob = NULL;
 	key_bloblen = 0;
 	key_blobtype = MM_NOKEY;
+	key_opts = NULL;
 	hostbased_cuser = NULL;
 	hostbased_chost = NULL;
 }
@@ -828,6 +833,7 @@
 int
 mm_answer_authpassword(int sock, Buffer *m)
 {
+	struct ssh *ssh = active_state;	/* XXX */
 	static int call_count;
 	char *passwd;
 	int authenticated;
@@ -838,7 +844,7 @@
 	passwd = buffer_get_string(m, &plen);
 	/* Only authenticate if the context is valid */
 	authenticated = options.password_authentication &&
-	    auth_password(authctxt, passwd);
+	    auth_password(ssh, passwd);
 	explicit_bzero(passwd, strlen(passwd));
 	free(passwd);
 
@@ -1129,15 +1135,16 @@
 int
 mm_answer_keyallowed(int sock, Buffer *m)
 {
+	struct ssh *ssh = active_state;	/* XXX */
 	struct sshkey *key;
 	char *cuser, *chost;
 	u_char *blob;
 	u_int bloblen, pubkey_auth_attempt;
 	enum mm_keytype type = 0;
-	int allowed = 0;
+	int r, allowed = 0;
+	struct sshauthopt *opts = NULL;
 
 	debug3("%s entering", __func__);
-
 	type = buffer_get_int(m);
 	cuser = buffer_get_string(m, NULL);
 	chost = buffer_get_string(m, NULL);
@@ -1156,28 +1163,31 @@
 
 		switch (type) {
 		case MM_USERKEY:
-			allowed = options.pubkey_authentication &&
-			    !auth2_key_already_used(authctxt, key) &&
-			    match_pattern_list(sshkey_ssh_name(key),
-			    options.pubkey_key_types, 0) == 1 &&
-			    user_key_allowed(authctxt->pw, key,
-			    pubkey_auth_attempt);
 			auth_method = "publickey";
-			if (options.pubkey_authentication &&
-			    (!pubkey_auth_attempt || allowed != 1))
-				auth_clear_options();
+			if (!options.pubkey_authentication)
+				break;
+			if (auth2_key_already_used(authctxt, key))
+				break;
+			if (match_pattern_list(sshkey_ssh_name(key),
+			    options.pubkey_key_types, 0) != 1)
+				break;
+			allowed = user_key_allowed(ssh, authctxt->pw, key,
+			    pubkey_auth_attempt, &opts);
 			break;
 		case MM_HOSTKEY:
-			allowed = options.hostbased_authentication &&
-			    !auth2_key_already_used(authctxt, key) &&
-			    match_pattern_list(sshkey_ssh_name(key),
-			    options.hostbased_key_types, 0) == 1 &&
-			    hostbased_key_allowed(authctxt->pw,
+			auth_method = "hostbased";
+			if (!options.hostbased_authentication)
+				break;
+			if (auth2_key_already_used(authctxt, key))
+				break;
+			if (match_pattern_list(sshkey_ssh_name(key),
+			    options.hostbased_key_types, 0) != 1)
+				break;
+			allowed = hostbased_key_allowed(authctxt->pw,
 			    cuser, chost, key);
 			auth2_record_info(authctxt,
 			    "client user \"%.100s\", client host \"%.100s\"",
 			    cuser, chost);
-			auth_method = "hostbased";
 			break;
 		default:
 			fatal("%s: unknown key type %d", __func__, type);
@@ -1185,7 +1195,10 @@
 		}
 	}
 
-	debug3("%s: key is %s", __func__, allowed ? "allowed" : "not allowed");
+	debug3("%s: %s authentication%s: %s key is %s", __func__,
+	    auth_method, pubkey_auth_attempt ? "" : " test",
+	    (key == NULL || !authctxt->valid) ? "invalid" : sshkey_type(key),
+	    allowed ? "allowed" : "not allowed");
 
 	auth2_record_key(authctxt, 0, key);
 	sshkey_free(key);
@@ -1198,6 +1211,7 @@
 		key_blob = blob;
 		key_bloblen = bloblen;
 		key_blobtype = type;
+		key_opts = opts;
 		hostbased_cuser = cuser;
 		hostbased_chost = chost;
 	} else {
@@ -1210,10 +1224,13 @@
 
 	buffer_clear(m);
 	buffer_put_int(m, allowed);
-	buffer_put_int(m, forced_command != NULL);
-
+	if (opts != NULL && (r = sshauthopt_serialise(opts, m, 1)) != 0)
+		fatal("%s: sshauthopt_serialise: %s", __func__, ssh_err(r));
 	mm_request_send(sock, MONITOR_ANS_KEYALLOWED, m);
 
+	if (!allowed)
+		sshauthopt_free(opts);
+
 	return (0);
 }
 
@@ -1336,6 +1353,7 @@
 int
 mm_answer_keyverify(int sock, struct sshbuf *m)
 {
+	struct ssh *ssh = active_state;	/* XXX */
 	struct sshkey *key;
 	u_char *signature, *data, *blob;
 	char *sigalg;
@@ -1390,6 +1408,8 @@
 	free(data);
 	free(sigalg);
 
+	if (key_blobtype == MM_USERKEY)
+		auth_activate_options(ssh, key_opts);
 	monitor_reset_key_state();
 
 	sshkey_free(key);