[openssh-commits] [openssh] 46/87: upstream: make StrictModes apply to ~/.k5login and the home

git+noreply at mindrot.org git+noreply at mindrot.org
Fri Oct 30 20:21:23 AEDT 2026


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit 22475508848bb3df9b794bd80b585e3a33e36eaa
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Fri Oct 30 04:52:11 2026 +0000

    upstream: make StrictModes apply to ~/.k5login and the home
    
    directory that contains it, just like how it applies to other authn-critical
    files.
    
    Anthropic ANT-2026-W7F2ULDN
    
    OpenBSD-Commit-ID: 33363fe797e8628906840bbd29254a24f5925c48
---
 gss-serv-krb5.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 gss-serv.c      |  6 +++---
 monitor.c       |  4 ++--
 ssh-gss.h       |  8 +++++---
 4 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index 4caac337c..cebb334ca 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gss-serv-krb5.c,v 1.10 2026/02/08 15:28:01 dtucker Exp $ */
+/* $OpenBSD: gss-serv-krb5.c,v 1.11 2026/10/30 04:52:11 djm Exp $ */
 
 /*
  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -30,8 +30,11 @@
 #ifdef KRB5
 
 #include <sys/types.h>
+#include <sys/stat.h>
 
+#include <pwd.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include "xmalloc.h"
@@ -76,13 +79,53 @@ ssh_gssapi_krb5_init(void)
 	return 1;
 }
 
+/*
+ * krb5_kuserok() consults the user's ~/.k5login but may check no more than
+ * its owner, so when StrictModes is set subject it and the home directory
+ * to the same ownership and mode checks as the user's other access lists
+ * (authorized_keys, .shosts, etc).
+ * Returns true if they are safe to use, otherwise returns 0
+ */
+
+static int
+ssh_gssapi_krb5_k5login_ok(struct passwd *pw)
+{
+	struct stat st;
+	char *path, err[1024];
+	int ok = 1;
+
+	if (!options.strict_modes)
+		return 1;
+
+	/*
+	 * Check the home directory first: anyone who can write to it can
+	 * supply a .k5login, and safe_path() does not see the directory a
+	 * symlink was planted in, only the one its target lives in.
+	 */
+	if (stat(pw->pw_dir, &st) == 0 &&
+	    ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
+	    (st.st_mode & 022) != 0)) {
+		logit("Authentication refused for %.100s: bad ownership or "
+		    "modes for home directory %.200s", pw->pw_name, pw->pw_dir);
+		return 0;
+	}
+	xasprintf(&path, "%s/.k5login", pw->pw_dir);
+	if (stat(path, &st) == 0 && safe_path(path, &st, pw->pw_dir,
+	    pw->pw_uid, err, sizeof(err)) != 0) {
+		logit("Authentication refused: %s", err);
+		ok = 0;
+	}
+	free(path);
+	return ok;
+}
+
 /* Check if this user is OK to login. This only works with krb5 - other
  * GSSAPI mechanisms will need their own.
  * Returns true if the user is OK to log in, otherwise returns 0
  */
 
 static int
-ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
+ssh_gssapi_krb5_userok(ssh_gssapi_client *client, struct passwd *pw)
 {
 	krb5_principal princ;
 	int retval;
@@ -91,6 +134,9 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
 	if (ssh_gssapi_krb5_init() == 0)
 		return 0;
 
+	if (!ssh_gssapi_krb5_k5login_ok(pw))
+		return 0;
+
 	if ((retval = krb5_parse_name(krb_context, client->exportedname.value,
 	    &princ))) {
 		errmsg = krb5_get_error_message(krb_context, retval);
@@ -98,10 +144,10 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
 		krb5_free_error_message(krb_context, errmsg);
 		return 0;
 	}
-	if (krb5_kuserok(krb_context, princ, name)) {
+	if (krb5_kuserok(krb_context, princ, pw->pw_name)) {
 		retval = 1;
 		logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
-		    name, (char *)client->displayname.value);
+		    pw->pw_name, (char *)client->displayname.value);
 	} else
 		retval = 0;
 
diff --git a/gss-serv.c b/gss-serv.c
index 32eaa4de0..d25eaf400 100644
--- a/gss-serv.c
+++ b/gss-serv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: gss-serv.c,v 1.40 2026/10/07 09:00:11 robert Exp $ */
+/* $OpenBSD: gss-serv.c,v 1.41 2026/10/30 04:52:11 djm Exp $ */
 
 /*
  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -380,7 +380,7 @@ ssh_gssapi_cleanup_global_client(void)
 
 /* Privileged */
 int
-ssh_gssapi_userok(char *user)
+ssh_gssapi_userok(struct passwd *pw)
 {
 	if (gssapi_client.exportedname.length == 0 ||
 	    gssapi_client.exportedname.value == NULL) {
@@ -388,7 +388,7 @@ ssh_gssapi_userok(char *user)
 		return 0;
 	}
 	if (gssapi_client.mech && gssapi_client.mech->userok)
-		if ((*gssapi_client.mech->userok)(&gssapi_client, user)) {
+		if ((*gssapi_client.mech->userok)(&gssapi_client, pw)) {
 			gssapi_client.userok = 1;
 			return 1;
 		} else {
diff --git a/monitor.c b/monitor.c
index f2890d26c..ebcd9c8c8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.262 2026/10/30 04:40:03 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.263 2026/10/30 04:52:11 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos at citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus at openbsd.org>
@@ -2096,7 +2096,7 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m)
 	if (!options.gss_authentication)
 		fatal_f("GSSAPI authentication not enabled");
 
-	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
+	authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->pw);
 
 	sshbuf_reset(m);
 	if ((r = sshbuf_put_u32(m, authenticated)) != 0)
diff --git a/ssh-gss.h b/ssh-gss.h
index d3cf70124..98fbd07fc 100644
--- a/ssh-gss.h
+++ b/ssh-gss.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-gss.h,v 1.19 2026/10/07 09:00:11 robert Exp $ */
+/* $OpenBSD: ssh-gss.h,v 1.20 2026/10/30 04:52:11 djm Exp $ */
 /*
  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
  *
@@ -61,6 +61,8 @@
 
 #define SSH_GSS_OIDTYPE 0x06
 
+struct passwd;
+
 typedef struct {
 	char *filename;
 	char *envvar;
@@ -82,7 +84,7 @@ typedef struct ssh_gssapi_mech_struct {
 	char *name;
 	gss_OID_desc oid;
 	int (*dochild) (ssh_gssapi_client *);
-	int (*userok) (ssh_gssapi_client *, char *);
+	int (*userok) (ssh_gssapi_client *, struct passwd *);
 	int (*localname) (ssh_gssapi_client *, char **);
 	void (*storecreds) (ssh_gssapi_client *);
 } ssh_gssapi_mech;
@@ -127,7 +129,7 @@ int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *);
 
 /* In the server */
 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
-int ssh_gssapi_userok(char *name);
+int ssh_gssapi_userok(struct passwd *);
 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
 void ssh_gssapi_do_child(char ***, u_int *);
 void ssh_gssapi_cleanup_creds(void);

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list