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
This commit is contained in:
djm@openbsd.org authored and Damien Miller committed 2026-10-30 20:14:14 +11:00
1 parent a73db88df0
commit 2247550884
4 files changed
+60 -12

No files matched your search

+50 -4
View File
@@ -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;
+3 -3
View File
@@ -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 {
+2 -2
View File
@@ -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@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@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)
+5 -3
View File
@@ -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);