git: 27ceebbc2402 - main - openssh: simplify login class restrictions

Ed Maste emaste at FreeBSD.org
Wed Sep 1 19:53:54 UTC 2021


The branch main has been updated by emaste:

URL: https://cgit.FreeBSD.org/src/commit/?id=27ceebbc2402e4c98203c7eef9696f4bd3d326f8

commit 27ceebbc2402e4c98203c7eef9696f4bd3d326f8
Author:     Ed Maste <emaste at FreeBSD.org>
AuthorDate: 2021-08-31 19:30:50 +0000
Commit:     Ed Maste <emaste at FreeBSD.org>
CommitDate: 2021-09-01 19:53:09 +0000

    openssh: simplify login class restrictions
    
    Login class-based restrictions were introduced in 5b400a39b8ad.  The
    code was adapted for sshd's Capsicum sandbox and received many changes
    over time, including at least fc3c19a9fcee, bd393de91cc3, and
    e8c56fba2926.
    
    During an attempt to upstream the work a much simpler approach was
    suggested.  Adopt it now in the in-tree OpenSSH to reduce conflicts with
    future updates.
    
    Submitted by:   Yuchiro Naito (against OpenSSH-portable on GitHub)
    Obtained from:  https://github.com/openssh/openssh-portable/pull/262
    Reviewed by:    allanjude, kevans
    MFC after:      2 weeks
    Differential Revision:  https://reviews.freebsd.org/D31760
---
 crypto/openssh/auth.c                |  18 +++++++
 crypto/openssh/auth2.c               |  19 -------
 crypto/openssh/config.h              |   6 +++
 crypto/openssh/configure.ac          |   2 +
 crypto/openssh/monitor.c             |  61 +++++----------------
 crypto/openssh/monitor.h             |   3 +-
 crypto/openssh/monitor_wrap.c        |  77 +++++++--------------------
 crypto/openssh/monitor_wrap.h        |   4 --
 crypto/openssh/ssh_namespace.h       |   3 --
 crypto/openssh/sshbuf-getput-basic.c | 100 -----------------------------------
 crypto/openssh/sshbuf.h              |  15 ------
 11 files changed, 58 insertions(+), 250 deletions(-)

diff --git a/crypto/openssh/auth.c b/crypto/openssh/auth.c
index 83be3cb5cbb5..a2e1fa10ce45 100644
--- a/crypto/openssh/auth.c
+++ b/crypto/openssh/auth.c
@@ -568,6 +568,9 @@ getpwnamallow(const char *user)
 	struct ssh *ssh = active_state; /* XXX */
 #ifdef HAVE_LOGIN_CAP
 	extern login_cap_t *lc;
+#ifdef HAVE_AUTH_HOSTOK
+	const char *from_host, *from_ip;
+#endif
 #ifdef BSD_AUTH
 	auth_session_t *as;
 #endif
@@ -622,6 +625,21 @@ getpwnamallow(const char *user)
 		debug("unable to get login class: %s", user);
 		return (NULL);
 	}
+#ifdef HAVE_AUTH_HOSTOK
+	from_host = auth_get_canonical_hostname(ssh, options.use_dns);
+	from_ip = ssh_remote_ipaddr(ssh);
+	if (!auth_hostok(lc, from_host, from_ip)) {
+		debug("Denied connection for %.200s from %.200s [%.200s].",
+		    pw->pw_name, from_host, from_ip);
+		return (NULL);
+	}
+#endif /* HAVE_AUTH_HOSTOK */
+#ifdef HAVE_AUTH_TIMEOK
+	if (!auth_timeok(lc, time(NULL))) {
+		debug("LOGIN %.200s REFUSED (TIME)", pw->pw_name);
+		return (NULL);
+	}
+#endif /* HAVE_AUTH_TIMEOK */
 #ifdef BSD_AUTH
 	if ((as = auth_open()) == NULL || auth_setpwd(as, pw) != 0 ||
 	    auth_approval(as, lc, pw->pw_name, "ssh") <= 0) {
diff --git a/crypto/openssh/auth2.c b/crypto/openssh/auth2.c
index 612cc3f8f2f3..af6fdae97193 100644
--- a/crypto/openssh/auth2.c
+++ b/crypto/openssh/auth2.c
@@ -314,25 +314,6 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
 		    authctxt->user, authctxt->service, user, service);
 	}
 
-#ifdef HAVE_LOGIN_CAP
-	if (authctxt->pw != NULL &&
-	    (lc = PRIVSEP(login_getpwclass(authctxt->pw))) != NULL) {
-		from_host = auth_get_canonical_hostname(ssh, options.use_dns);
-		from_ip = ssh_remote_ipaddr(ssh);
-		if (!auth_hostok(lc, from_host, from_ip)) {
-			logit("Denied connection for %.200s from %.200s [%.200s].",
-			    authctxt->pw->pw_name, from_host, from_ip);
-			packet_disconnect("Sorry, you are not allowed to connect.");
-		}
-		if (!auth_timeok(lc, time(NULL))) {
-			logit("LOGIN %.200s REFUSED (TIME) FROM %.200s",
-			    authctxt->pw->pw_name, from_host);
-			packet_disconnect("Logins not available right now.");
-		}
-		PRIVSEP(login_close(lc));
-	}
-#endif  /* HAVE_LOGIN_CAP */
-
 	/* reset state */
 	auth2_challenge_stop(ssh);
 
diff --git a/crypto/openssh/config.h b/crypto/openssh/config.h
index 17d7e53666e9..dbdad4faaca1 100644
--- a/crypto/openssh/config.h
+++ b/crypto/openssh/config.h
@@ -211,6 +211,12 @@
 /* Define to 1 if you have the `aug_get_machine' function. */
 /* #undef HAVE_AUG_GET_MACHINE */
 
+/* Define to 1 if you have the `auth_hostok' function. */
+#define HAVE_AUTH_HOSTOK 1
+
+/* Define to 1 if you have the `auth_timeok' function. */
+#define HAVE_AUTH_TIMEOK 1
+
 /* Define to 1 if you have the `b64_ntop' function. */
 /* #undef HAVE_B64_NTOP */
 
diff --git a/crypto/openssh/configure.ac b/crypto/openssh/configure.ac
index 60c170285979..538f389c6da3 100644
--- a/crypto/openssh/configure.ac
+++ b/crypto/openssh/configure.ac
@@ -1751,6 +1751,8 @@ fi
 
 dnl    Checks for library functions. Please keep in alphabetical order
 AC_CHECK_FUNCS([ \
+	auth_hostok \
+	auth_timeok \
 	Blowfish_initstate \
 	Blowfish_expandstate \
 	Blowfish_expand0state \
diff --git a/crypto/openssh/monitor.c b/crypto/openssh/monitor.c
index c5e3708c2563..531b2993ab6b 100644
--- a/crypto/openssh/monitor.c
+++ b/crypto/openssh/monitor.c
@@ -114,9 +114,6 @@ static struct sshbuf *child_state;
 
 int mm_answer_moduli(int, struct sshbuf *);
 int mm_answer_sign(int, struct sshbuf *);
-#ifdef HAVE_LOGIN_CAP
-int mm_answer_login_getpwclass(int, struct sshbuf *);
-#endif
 int mm_answer_pwnamallow(int, struct sshbuf *);
 int mm_answer_auth2_read_banner(int, struct sshbuf *);
 int mm_answer_authserv(int, struct sshbuf *);
@@ -192,9 +189,6 @@ struct mon_table mon_dispatch_proto20[] = {
     {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
 #endif
     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
-#ifdef HAVE_LOGIN_CAP
-    {MONITOR_REQ_GETPWCLASS, MON_ISAUTH, mm_answer_login_getpwclass},
-#endif
     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
     {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
@@ -713,48 +707,6 @@ mm_answer_sign(int sock, struct sshbuf *m)
 	return (0);
 }
 
-#ifdef HAVE_LOGIN_CAP
-int
-mm_answer_login_getpwclass(int sock, struct sshbuf *m)
-{
-	login_cap_t *lc;
-	struct passwd *pw;
-	int r;
-	u_int len;
-
-	debug3("%s", __func__);
-
-	pw = sshbuf_get_passwd(m);
-	if (pw == NULL)
-		fatal("%s: receive get struct passwd failed", __func__);
-
-	lc = login_getpwclass(pw);
-
-	sshbuf_reset(m);
-
-	if (lc == NULL) {
-		if (r = sshbuf_put_u8(m, 0) != 0)
-			fatal("%s: buffer error: %s", __func__, ssh_err(r));
-		goto out;
-	}
-
-	if ((r = sshbuf_put_u8(m, 1)) != 0 ||
-	    (r = sshbuf_put_cstring(m, lc->lc_class)) != 0 ||
-	    (r = sshbuf_put_cstring(m, lc->lc_cap)) != 0 ||
-	    (r = sshbuf_put_cstring(m, lc->lc_style)) != 0)
-		fatal("%s: buffer error: %s", __func__, ssh_err(r));
-
-	login_close(lc);
- out:
-	debug3("%s: sending MONITOR_ANS_GETPWCLASS", __func__);
-	mm_request_send(sock, MONITOR_ANS_GETPWCLASS, m);
-
-	sshbuf_free_passwd(pw);
-
-	return (0);
-}
-#endif
-
 /* Retrieves the password entry and also checks if the user is permitted */
 
 int
@@ -793,8 +745,19 @@ mm_answer_pwnamallow(int sock, struct sshbuf *m)
 	authctxt->pw = pwent;
 	authctxt->valid = 1;
 
+	/* XXX don't sent pwent to unpriv; send fake class/dir/shell too */
 	if ((r = sshbuf_put_u8(m, 1)) != 0 ||
-	    (r = sshbuf_put_passwd(m, pwent)) != 0)
+	    (r = sshbuf_put_string(m, pwent, sizeof(*pwent))) != 0 ||
+	    (r = sshbuf_put_cstring(m, pwent->pw_name)) != 0 ||
+	    (r = sshbuf_put_cstring(m, "*")) != 0 ||
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
+	    (r = sshbuf_put_cstring(m, pwent->pw_gecos)) != 0 ||
+#endif
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
+	    (r = sshbuf_put_cstring(m, pwent->pw_class)) != 0 ||
+#endif
+	    (r = sshbuf_put_cstring(m, pwent->pw_dir)) != 0 ||
+	    (r = sshbuf_put_cstring(m, pwent->pw_shell)) != 0)
 		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
  out:
diff --git a/crypto/openssh/monitor.h b/crypto/openssh/monitor.h
index abf2ca4018b4..16047299f882 100644
--- a/crypto/openssh/monitor.h
+++ b/crypto/openssh/monitor.h
@@ -53,8 +53,7 @@ enum monitor_reqtype {
 	MONITOR_REQ_GSSSTEP = 44, MONITOR_ANS_GSSSTEP = 45,
 	MONITOR_REQ_GSSUSEROK = 46, MONITOR_ANS_GSSUSEROK = 47,
 	MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49,
-	MONITOR_REQ_GETPWCLASS = 50, MONITOR_ANS_GETPWCLASS = 51,
-	MONITOR_REQ_TERM = 52,
+	MONITOR_REQ_TERM = 50,
 
 	MONITOR_REQ_PAM_START = 100,
 	MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103,
diff --git a/crypto/openssh/monitor_wrap.c b/crypto/openssh/monitor_wrap.c
index bb458f131483..732fb3476bf0 100644
--- a/crypto/openssh/monitor_wrap.c
+++ b/crypto/openssh/monitor_wrap.c
@@ -247,61 +247,6 @@ mm_sshkey_sign(struct sshkey *key, u_char **sigp, size_t *lenp,
 	return (0);
 }
 
-#ifdef HAVE_LOGIN_CAP
-login_cap_t *
-mm_login_getpwclass(const struct passwd *pwent)
-{
-	int r;
-	struct sshbuf *m;
-	char rc;
-	login_cap_t *lc;
-
-	debug3("%s entering", __func__);
-
-	if ((m = sshbuf_new()) == NULL)
-		fatal("%s: sshbuf_new failed", __func__);
-	if ((r = sshbuf_put_passwd(m, pwent)) != 0)
-		fatal("%s: buffer error: %s", __func__, ssh_err(r));
-
-	mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GETPWCLASS, m);
-
-	debug3("%s: waiting for MONITOR_ANS_GETPWCLASS", __func__);
-	mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GETPWCLASS, m);
-
-	if ((r = sshbuf_get_u8(m, &rc)) != 0)
-		fatal("%s: buffer error: %s", __func__, ssh_err(r));
-
-	if (rc == 0) {
-		lc = NULL;
-		goto out;
-	}
-
-	lc = xmalloc(sizeof(*lc));
-	if ((r = sshbuf_get_cstring(m, &lc->lc_class, NULL)) != 0 ||
-	    (r = sshbuf_get_cstring(m, &lc->lc_cap, NULL)) != 0 ||
-	    (r = sshbuf_get_cstring(m, &lc->lc_style, NULL)) != 0)
-		fatal("%s: buffer error: %s", __func__, ssh_err(r));
-
- out:
-	sshbuf_free(m);
-
-	return (lc);
-}
-#endif
-
-#ifdef HAVE_LOGIN_CAP
-void
-mm_login_close(login_cap_t *lc)
-{
-	if (lc == NULL)
-		return;
-	free(lc->lc_style);
-	free(lc->lc_class);
-	free(lc->lc_cap);
-	free(lc);
-}
-#endif
-
 struct passwd *
 mm_getpwnamallow(const char *username)
 {
@@ -334,9 +279,25 @@ mm_getpwnamallow(const char *username)
 		goto out;
 	}
 
-	pw = sshbuf_get_passwd(m);
-	if (pw == NULL)
-		fatal("%s: receive get struct passwd failed", __func__);
+	/* XXX don't like passing struct passwd like this */
+	pw = xcalloc(sizeof(*pw), 1);
+	if ((r = sshbuf_get_string_direct(m, &p, &len)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	if (len != sizeof(*pw))
+		fatal("%s: struct passwd size mismatch", __func__);
+	memcpy(pw, p, sizeof(*pw));
+
+	if ((r = sshbuf_get_cstring(m, &pw->pw_name, NULL)) != 0 ||
+	    (r = sshbuf_get_cstring(m, &pw->pw_passwd, NULL)) != 0 ||
+#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
+	    (r = sshbuf_get_cstring(m, &pw->pw_gecos, NULL)) != 0 ||
+#endif
+#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
+	    (r = sshbuf_get_cstring(m, &pw->pw_class, NULL)) != 0 ||
+#endif
+	    (r = sshbuf_get_cstring(m, &pw->pw_dir, NULL)) != 0 ||
+	    (r = sshbuf_get_cstring(m, &pw->pw_shell, NULL)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
 out:
 	/* copy options block as a Match directive may have changed some */
diff --git a/crypto/openssh/monitor_wrap.h b/crypto/openssh/monitor_wrap.h
index 5b5dea1ed828..644da081db8d 100644
--- a/crypto/openssh/monitor_wrap.h
+++ b/crypto/openssh/monitor_wrap.h
@@ -44,10 +44,6 @@ DH *mm_choose_dh(int, int, int);
 int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t,
     const char *, u_int compat);
 void mm_inform_authserv(char *, char *);
-#ifdef HAVE_LOGIN_CAP
-struct login_cap *mm_login_getpwclass(const struct passwd *pwd);
-void mm_login_close(struct login_cap *lc);
-#endif
 struct passwd *mm_getpwnamallow(const char *);
 char *mm_auth2_read_banner(void);
 int mm_auth_password(struct ssh *, char *);
diff --git a/crypto/openssh/ssh_namespace.h b/crypto/openssh/ssh_namespace.h
index f6a100622de8..57b7bb3e375c 100644
--- a/crypto/openssh/ssh_namespace.h
+++ b/crypto/openssh/ssh_namespace.h
@@ -657,7 +657,6 @@
 #define sshbuf_dump_data			Fssh_sshbuf_dump_data
 #define sshbuf_dup_string			Fssh_sshbuf_dup_string
 #define sshbuf_free				Fssh_sshbuf_free
-#define sshbuf_free_passwd			Fssh_sshbuf_free_passwd
 #define sshbuf_from				Fssh_sshbuf_from
 #define sshbuf_fromb				Fssh_sshbuf_fromb
 #define sshbuf_froms				Fssh_sshbuf_froms
@@ -668,7 +667,6 @@
 #define sshbuf_get_cstring			Fssh_sshbuf_get_cstring
 #define sshbuf_get_ec				Fssh_sshbuf_get_ec
 #define sshbuf_get_eckey			Fssh_sshbuf_get_eckey
-#define sshbuf_get_passwd			Fssh_sshbuf_get_passwd
 #define sshbuf_get_string			Fssh_sshbuf_get_string
 #define sshbuf_get_string_direct		Fssh_sshbuf_get_string_direct
 #define sshbuf_get_stringb			Fssh_sshbuf_get_stringb
@@ -690,7 +688,6 @@
 #define sshbuf_put_cstring			Fssh_sshbuf_put_cstring
 #define sshbuf_put_ec				Fssh_sshbuf_put_ec
 #define sshbuf_put_eckey			Fssh_sshbuf_put_eckey
-#define sshbuf_put_passwd			Fssh_sshbuf_put_passwd
 #define sshbuf_put_string			Fssh_sshbuf_put_string
 #define sshbuf_put_stringb			Fssh_sshbuf_put_stringb
 #define sshbuf_put_u16				Fssh_sshbuf_put_u16
diff --git a/crypto/openssh/sshbuf-getput-basic.c b/crypto/openssh/sshbuf-getput-basic.c
index 70ee303a23e4..9092a7eebf97 100644
--- a/crypto/openssh/sshbuf-getput-basic.c
+++ b/crypto/openssh/sshbuf-getput-basic.c
@@ -463,103 +463,3 @@ sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf,
 	}
 	return 0;
 }
-
-/*
- * store struct pwd
- */
-int
-sshbuf_put_passwd(struct sshbuf *buf, const struct passwd *pwent)
-{
-	int r;
-
-	/*
-	 * We never send pointer values of struct passwd.
-	 * It is safe from wild pointer even if a new pointer member is added.
-	 */
-
-	if ((r = sshbuf_put_u64(buf, sizeof(*pwent)) != 0) ||
-	    (r = sshbuf_put_cstring(buf, pwent->pw_name)) != 0 ||
-	    (r = sshbuf_put_cstring(buf, "*")) != 0 ||
-	    (r = sshbuf_put_u32(buf, pwent->pw_uid)) != 0 ||
-	    (r = sshbuf_put_u32(buf, pwent->pw_gid)) != 0 ||
-#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
-	    (r = sshbuf_put_time(buf, pwent->pw_change)) != 0 ||
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
-	    (r = sshbuf_put_cstring(buf, pwent->pw_gecos)) != 0 ||
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
-	    (r = sshbuf_put_cstring(buf, pwent->pw_class)) != 0 ||
-#endif
-	    (r = sshbuf_put_cstring(buf, pwent->pw_dir)) != 0 ||
-	    (r = sshbuf_put_cstring(buf, pwent->pw_shell)) != 0 ||
-#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
-	    (r = sshbuf_put_time(buf, pwent->pw_expire)) != 0 ||
-#endif
-	    (r = sshbuf_put_u32(buf, pwent->pw_fields)) != 0) {
-		return r;
-	}
-	return 0;
-}
-
-/*
- * extract struct pwd
- */
-struct passwd *
-sshbuf_get_passwd(struct sshbuf *buf)
-{
-	struct passwd *pw;
-	u_int64_t len;
-	int r;
-
-	/* check if size of struct passwd is as same as sender's size */
-	r = sshbuf_get_u64(buf, &len);
-	if (r != 0 || len != sizeof(*pw))
-		return NULL;
-
-	pw = xcalloc(1, sizeof(*pw));
-	if (sshbuf_get_cstring(buf, &pw->pw_name, NULL) != 0 ||
-	    sshbuf_get_cstring(buf, &pw->pw_passwd, NULL) != 0 ||
-	    sshbuf_get_u32(buf, &pw->pw_uid) != 0 ||
-	    sshbuf_get_u32(buf, &pw->pw_gid) != 0 ||
-#ifdef HAVE_STRUCT_PASSWD_PW_CHANGE
-	    sshbuf_get_time(buf, &pw->pw_change) != 0 ||
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
-	    sshbuf_get_cstring(buf, &pw->pw_gecos, NULL) != 0 ||
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
-	    sshbuf_get_cstring(buf, &pw->pw_class, NULL) != 0 ||
-#endif
-	    sshbuf_get_cstring(buf, &pw->pw_dir, NULL) != 0 ||
-	    sshbuf_get_cstring(buf, &pw->pw_shell, NULL) != 0 ||
-#ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
-	    sshbuf_get_time(buf, &pw->pw_expire) != 0 ||
-#endif
-	    sshbuf_get_u32(buf, &pw->pw_fields) != 0) {
-		sshbuf_free_passwd(pw);
-		return NULL;
-	}
-	return pw;
-}
-
-/*
- * free struct passwd obtained from sshbuf_get_passwd.
- */
-void
-sshbuf_free_passwd(struct passwd *pwent)
-{
-	if (pwent == NULL)
-		return;
-	free(pwent->pw_shell);
-	free(pwent->pw_dir);
-#ifdef HAVE_STRUCT_PASSWD_PW_CLASS
-	free(pwent->pw_class);
-#endif
-#ifdef HAVE_STRUCT_PASSWD_PW_GECOS
-	free(pwent->pw_gecos);
-#endif
-	free(pwent->pw_passwd);
-	free(pwent->pw_name);
-	free(pwent);
-}
diff --git a/crypto/openssh/sshbuf.h b/crypto/openssh/sshbuf.h
index aba18d2aa922..87aa1560eabe 100644
--- a/crypto/openssh/sshbuf.h
+++ b/crypto/openssh/sshbuf.h
@@ -254,21 +254,6 @@ int	sshbuf_b64tod(struct sshbuf *buf, const char *b64);
  */
 char *sshbuf_dup_string(struct sshbuf *buf);
 
-/*
- * store struct pwd
- */
-int sshbuf_put_passwd(struct sshbuf *buf, const struct passwd *pwent);
-
-/*
- * extract struct pwd
- */
-struct passwd *sshbuf_get_passwd(struct sshbuf *buf);
-
-/*
- * free struct passwd obtained from sshbuf_get_passwd.
- */
-void sshbuf_free_passwd(struct passwd *pwent);
-
 /* Macros for decoding/encoding integers */
 #define PEEK_U64(p) \
 	(((u_int64_t)(((const u_char *)(p))[0]) << 56) | \


More information about the dev-commits-src-all mailing list