1
0
Fork 0
openssh/debian/patches/selinux-role.patch
Daniel Baumann 31f6d7a384
Adding debian version 1:10.0p1-5.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-21 09:50:02 +02:00

461 lines
16 KiB
Diff

From ad6e66e766ecc3a76c62c6daf81ebf19432713cb Mon Sep 17 00:00:00 2001
From: Manoj Srivastava <srivasta@debian.org>
Date: Sun, 9 Feb 2014 16:09:49 +0000
Subject: Handle SELinux authorisation roles
Rejected upstream due to discomfort with magic usernames; a better approach
will need an SSH protocol change. In the meantime, this came from Debian's
SELinux maintainer, so we'll keep it until we have something better.
Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1641
Bug-Debian: http://bugs.debian.org/394795
Last-Update: 2024-07-03
Patch-Name: selinux-role.patch
---
auth.h | 1 +
auth2.c | 10 ++++++++--
monitor.c | 36 +++++++++++++++++++++++++++++++++---
monitor.h | 2 ++
monitor_wrap.c | 27 ++++++++++++++++++++++++---
monitor_wrap.h | 3 ++-
openbsd-compat/port-linux.c | 21 ++++++++++++++-------
openbsd-compat/port-linux.h | 4 ++--
platform.c | 4 ++--
platform.h | 2 +-
session.c | 8 ++++----
session.h | 2 +-
sshd-session.c | 2 +-
sshpty.c | 4 ++--
sshpty.h | 2 +-
15 files changed, 98 insertions(+), 30 deletions(-)
diff --git a/auth.h b/auth.h
index 98bb23d4c..59799a812 100644
--- a/auth.h
+++ b/auth.h
@@ -65,6 +65,7 @@ struct Authctxt {
char *service;
struct passwd *pw; /* set if 'valid' */
char *style;
+ char *role;
/* Method lists for multiple authentication */
char **auth_methods; /* modified from server config */
diff --git a/auth2.c b/auth2.c
index 4fff5a5f7..7ca8a96f8 100644
--- a/auth2.c
+++ b/auth2.c
@@ -272,7 +272,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
{
Authctxt *authctxt = ssh->authctxt;
Authmethod *m = NULL;
- char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
+ char *user = NULL, *service = NULL, *method = NULL, *style = NULL, *role = NULL;
int r, authenticated = 0;
double tstart = monotime_double();
@@ -286,8 +286,13 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
debug("userauth-request for user %s service %s method %s", user, service, method);
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
+ if ((role = strchr(user, '/')) != NULL)
+ *role++ = 0;
+
if ((style = strchr(user, ':')) != NULL)
*style++ = 0;
+ else if (role && (style = strchr(role, ':')) != NULL)
+ *style++ = '\0';
if (authctxt->attempt >= 1024)
auth_maxtries_exceeded(ssh);
@@ -315,7 +320,8 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
setproctitle("%s [net]", authctxt->valid ? user : "unknown");
authctxt->service = xstrdup(service);
authctxt->style = style ? xstrdup(style) : NULL;
- mm_inform_authserv(service, style);
+ authctxt->role = role ? xstrdup(role) : NULL;
+ mm_inform_authserv(service, style, role);
userauth_banner(ssh);
if ((r = kex_server_update_ext_info(ssh)) != 0)
fatal_fr(r, "kex_server_update_ext_info failed");
diff --git a/monitor.c b/monitor.c
index 1aa81094e..180c6dbbc 100644
--- a/monitor.c
+++ b/monitor.c
@@ -120,6 +120,7 @@ int mm_answer_sign(struct ssh *, int, struct sshbuf *);
int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
+int mm_answer_authrole(struct ssh *, int, struct sshbuf *);
int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
@@ -196,6 +197,7 @@ struct mon_table mon_dispatch_proto20[] = {
{MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
{MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
{MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
+ {MONITOR_REQ_AUTHROLE, MON_ONCE, mm_answer_authrole},
{MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
{MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
#ifdef USE_PAM
@@ -929,6 +931,7 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
/* Allow service/style information on the auth context */
monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
+ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHROLE, 1);
monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
#ifdef USE_PAM
@@ -962,15 +965,42 @@ mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m)
monitor_permit_authentications(1);
if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 ||
- (r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0)
+ (r = sshbuf_get_cstring(m, &authctxt->style, NULL)) != 0 ||
+ (r = sshbuf_get_cstring(m, &authctxt->role, NULL)) != 0)
fatal_fr(r, "parse");
- debug3_f("service=%s, style=%s", authctxt->service, authctxt->style);
+ debug3_f("service=%s, style=%s, role=%s",
+ authctxt->service, authctxt->style, authctxt->role);
if (strlen(authctxt->style) == 0) {
free(authctxt->style);
authctxt->style = NULL;
}
+ if (strlen(authctxt->role) == 0) {
+ free(authctxt->role);
+ authctxt->role = NULL;
+ }
+
+ return (0);
+}
+
+int
+mm_answer_authrole(struct ssh *ssh, int sock, struct sshbuf *m)
+{
+ int r;
+
+ monitor_permit_authentications(1);
+
+ if ((r = sshbuf_get_cstring(m, &authctxt->role, NULL)) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+ debug3("%s: role=%s",
+ __func__, authctxt->role);
+
+ if (strlen(authctxt->role) == 0) {
+ free(authctxt->role);
+ authctxt->role = NULL;
+ }
+
return (0);
}
@@ -1691,7 +1721,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
if (res == 0)
goto error;
- pty_setowner(authctxt->pw, s->tty);
+ pty_setowner(authctxt->pw, s->tty, authctxt->role);
if ((r = sshbuf_put_u32(m, 1)) != 0 ||
(r = sshbuf_put_cstring(m, s->tty)) != 0)
diff --git a/monitor.h b/monitor.h
index 4076f71ea..1eda94540 100644
--- a/monitor.h
+++ b/monitor.h
@@ -66,6 +66,8 @@ enum monitor_reqtype {
MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151,
MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153,
+
+ MONITOR_REQ_AUTHROLE = 154,
};
struct ssh;
diff --git a/monitor_wrap.c b/monitor_wrap.c
index 8a6b4442f..9bf62aac2 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -421,10 +421,10 @@ mm_auth2_read_banner(void)
return (banner);
}
-/* Inform the privileged process about service and style */
+/* Inform the privileged process about service, style, and role */
void
-mm_inform_authserv(char *service, char *style)
+mm_inform_authserv(char *service, char *style, char *role)
{
struct sshbuf *m;
int r;
@@ -434,7 +434,8 @@ mm_inform_authserv(char *service, char *style)
if ((m = sshbuf_new()) == NULL)
fatal_f("sshbuf_new failed");
if ((r = sshbuf_put_cstring(m, service)) != 0 ||
- (r = sshbuf_put_cstring(m, style ? style : "")) != 0)
+ (r = sshbuf_put_cstring(m, style ? style : "")) != 0 ||
+ (r = sshbuf_put_cstring(m, role ? role : "")) != 0)
fatal_fr(r, "assemble");
mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
@@ -442,6 +443,26 @@ mm_inform_authserv(char *service, char *style)
sshbuf_free(m);
}
+/* Inform the privileged process about role */
+
+void
+mm_inform_authrole(char *role)
+{
+ struct sshbuf *m;
+ int r;
+
+ debug3("%s entering", __func__);
+
+ if ((m = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new failed", __func__);
+ if ((r = sshbuf_put_cstring(m, role ? role : "")) != 0)
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
+
+ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHROLE, m);
+
+ sshbuf_free(m);
+}
+
/* Do the password authentication */
int
mm_auth_password(struct ssh *ssh, char *password)
diff --git a/monitor_wrap.h b/monitor_wrap.h
index 01251cf1b..fb6d7e15b 100644
--- a/monitor_wrap.h
+++ b/monitor_wrap.h
@@ -45,7 +45,8 @@ DH *mm_choose_dh(int, int, int);
int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *,
const u_char *, size_t, const char *, const char *,
const char *, u_int compat);
-void mm_inform_authserv(char *, char *);
+void mm_inform_authserv(char *, char *, char *);
+void mm_inform_authrole(char *);
struct passwd *mm_getpwnamallow(struct ssh *, const char *);
char *mm_auth2_read_banner(void);
int mm_auth_password(struct ssh *, char *);
diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
index c1d54f38d..1fd3bfa81 100644
--- a/openbsd-compat/port-linux.c
+++ b/openbsd-compat/port-linux.c
@@ -65,7 +65,7 @@ ssh_selinux_enabled(void)
/* Return the default security context for the given username */
static char *
-ssh_selinux_getctxbyname(char *pwname)
+ssh_selinux_getctxbyname(char *pwname, const char *role)
{
char *sc = NULL, *sename = NULL, *lvl = NULL;
int r;
@@ -79,9 +79,16 @@ ssh_selinux_getctxbyname(char *pwname)
#endif
#ifdef HAVE_GET_DEFAULT_CONTEXT_WITH_LEVEL
- r = get_default_context_with_level(sename, lvl, NULL, &sc);
+ if (role != NULL && role[0])
+ r = get_default_context_with_rolelevel(sename, role, lvl, NULL,
+ &sc);
+ else
+ r = get_default_context_with_level(sename, lvl, NULL, &sc);
#else
- r = get_default_context(sename, NULL, &sc);
+ if (role != NULL && role[0])
+ r = get_default_context_with_role(sename, role, NULL, &sc);
+ else
+ r = get_default_context(sename, NULL, &sc);
#endif
if (r != 0) {
@@ -111,7 +118,7 @@ ssh_selinux_getctxbyname(char *pwname)
/* Set the execution context to the default for the specified user */
void
-ssh_selinux_setup_exec_context(char *pwname)
+ssh_selinux_setup_exec_context(char *pwname, const char *role)
{
char *user_ctx = NULL;
@@ -120,7 +127,7 @@ ssh_selinux_setup_exec_context(char *pwname)
debug3("%s: setting execution context", __func__);
- user_ctx = ssh_selinux_getctxbyname(pwname);
+ user_ctx = ssh_selinux_getctxbyname(pwname, role);
if (setexeccon(user_ctx) != 0) {
switch (security_getenforce()) {
case -1:
@@ -142,7 +149,7 @@ ssh_selinux_setup_exec_context(char *pwname)
/* Set the TTY context for the specified user */
void
-ssh_selinux_setup_pty(char *pwname, const char *tty)
+ssh_selinux_setup_pty(char *pwname, const char *tty, const char *role)
{
char *new_tty_ctx = NULL, *user_ctx = NULL, *old_tty_ctx = NULL;
security_class_t chrclass;
@@ -152,7 +159,7 @@ ssh_selinux_setup_pty(char *pwname, const char *tty)
debug3("%s: setting TTY context on %s", __func__, tty);
- user_ctx = ssh_selinux_getctxbyname(pwname);
+ user_ctx = ssh_selinux_getctxbyname(pwname, role);
/* XXX: should these calls fatal() upon failure in enforcing mode? */
diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h
index 959430de1..7f9a7c195 100644
--- a/openbsd-compat/port-linux.h
+++ b/openbsd-compat/port-linux.h
@@ -19,8 +19,8 @@
#ifdef WITH_SELINUX
int ssh_selinux_enabled(void);
-void ssh_selinux_setup_pty(char *, const char *);
-void ssh_selinux_setup_exec_context(char *);
+void ssh_selinux_setup_pty(char *, const char *, const char *);
+void ssh_selinux_setup_exec_context(char *, const char *);
void ssh_selinux_change_context(const char *);
void ssh_selinux_setfscreatecon(const char *);
#endif
diff --git a/platform.c b/platform.c
index 4c4fe57ea..f3dc7c3a8 100644
--- a/platform.c
+++ b/platform.c
@@ -99,7 +99,7 @@ platform_setusercontext(struct passwd *pw)
* called if sshd is running as root.
*/
void
-platform_setusercontext_post_groups(struct passwd *pw)
+platform_setusercontext_post_groups(struct passwd *pw, const char *role)
{
#if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
/*
@@ -140,7 +140,7 @@ platform_setusercontext_post_groups(struct passwd *pw)
}
#endif /* HAVE_SETPCRED */
#ifdef WITH_SELINUX
- ssh_selinux_setup_exec_context(pw->pw_name);
+ ssh_selinux_setup_exec_context(pw->pw_name, role);
#endif
}
diff --git a/platform.h b/platform.h
index 08cbd225d..2a7364578 100644
--- a/platform.h
+++ b/platform.h
@@ -27,7 +27,7 @@ void platform_post_fork_child(void);
void platform_pre_session_start(void);
int platform_privileged_uidswap(void);
void platform_setusercontext(struct passwd *);
-void platform_setusercontext_post_groups(struct passwd *);
+void platform_setusercontext_post_groups(struct passwd *, const char *);
char *platform_get_krb5_client(const char *);
char *platform_krb5_get_principal_name(const char *);
int platform_locked_account(struct passwd *);
diff --git a/session.c b/session.c
index b3833e44c..6614d8560 100644
--- a/session.c
+++ b/session.c
@@ -1344,7 +1344,7 @@ safely_chroot(const char *path, uid_t uid)
/* Set login name, uid, gid, and groups. */
void
-do_setusercontext(struct passwd *pw)
+do_setusercontext(struct passwd *pw, const char *role)
{
char uidstr[32], *chroot_path, *tmp;
@@ -1372,7 +1372,7 @@ do_setusercontext(struct passwd *pw)
endgrent();
#endif
- platform_setusercontext_post_groups(pw);
+ platform_setusercontext_post_groups(pw, role);
if (!in_chroot && options.chroot_directory != NULL &&
strcasecmp(options.chroot_directory, "none") != 0) {
@@ -1515,7 +1515,7 @@ do_child(struct ssh *ssh, Session *s, const char *command)
/* Force a password change */
if (s->authctxt->force_pwchange) {
- do_setusercontext(pw);
+ do_setusercontext(pw, s->authctxt->role);
child_close_fds(ssh);
do_pwchange(s);
exit(1);
@@ -1533,7 +1533,7 @@ do_child(struct ssh *ssh, Session *s, const char *command)
/* When PAM is enabled we rely on it to do the nologin check */
if (!options.use_pam)
do_nologin(pw);
- do_setusercontext(pw);
+ do_setusercontext(pw, s->authctxt->role);
/*
* PAM session modules in do_setusercontext may have
* generated messages, so if this in an interactive
diff --git a/session.h b/session.h
index 344a1ddf9..20ea822a7 100644
--- a/session.h
+++ b/session.h
@@ -77,7 +77,7 @@ void session_pty_cleanup2(Session *);
Session *session_new(void);
Session *session_by_tty(char *);
void session_close(struct ssh *, Session *);
-void do_setusercontext(struct passwd *);
+void do_setusercontext(struct passwd *, const char *);
const char *session_get_remote_name_or_ip(struct ssh *, u_int, int);
diff --git a/sshd-session.c b/sshd-session.c
index c171c8923..372a610b3 100644
--- a/sshd-session.c
+++ b/sshd-session.c
@@ -471,7 +471,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
/* Drop privileges */
if (!skip_privdrop)
- do_setusercontext(authctxt->pw);
+ do_setusercontext(authctxt->pw, authctxt->role);
/* It is safe now to apply the key state */
monitor_apply_keystate(ssh, pmonitor);
diff --git a/sshpty.c b/sshpty.c
index cae0b977a..7870c6482 100644
--- a/sshpty.c
+++ b/sshpty.c
@@ -163,7 +163,7 @@ pty_change_window_size(int ptyfd, u_int row, u_int col,
}
void
-pty_setowner(struct passwd *pw, const char *tty)
+pty_setowner(struct passwd *pw, const char *tty, const char *role)
{
struct group *grp;
gid_t gid;
@@ -187,7 +187,7 @@ pty_setowner(struct passwd *pw, const char *tty)
strerror(errno));
#ifdef WITH_SELINUX
- ssh_selinux_setup_pty(pw->pw_name, tty);
+ ssh_selinux_setup_pty(pw->pw_name, tty, role);
#endif
if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
diff --git a/sshpty.h b/sshpty.h
index 9ec7e9a15..de7e000ae 100644
--- a/sshpty.h
+++ b/sshpty.h
@@ -24,5 +24,5 @@ int pty_allocate(int *, int *, char *, size_t);
void pty_release(const char *);
void pty_make_controlling_tty(int *, const char *);
void pty_change_window_size(int, u_int, u_int, u_int, u_int);
-void pty_setowner(struct passwd *, const char *);
+void pty_setowner(struct passwd *, const char *, const char *);
void disconnect_controlling_tty(void);