[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