summaryrefslogtreecommitdiffstats
path: root/debian/patches/selinux-role.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/selinux-role.patch')
-rw-r--r--debian/patches/selinux-role.patch471
1 files changed, 471 insertions, 0 deletions
diff --git a/debian/patches/selinux-role.patch b/debian/patches/selinux-role.patch
new file mode 100644
index 0000000..7fb35f2
--- /dev/null
+++ b/debian/patches/selinux-role.patch
@@ -0,0 +1,471 @@
+From a1b3f6592e7ef61f5d9544fc652ae44f8c47bd2e 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: 2021-11-05
+
+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 | 10 +++++-----
+ session.h | 2 +-
+ sshd.c | 2 +-
+ sshpty.c | 4 ++--
+ sshpty.h | 2 +-
+ 15 files changed, 99 insertions(+), 31 deletions(-)
+
+diff --git a/auth.h b/auth.h
+index 6d2d39762..d16dc66b8 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 44bd49177..d66d73876 100644
+--- a/auth2.c
++++ b/auth2.c
+@@ -264,7 +264,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();
+
+@@ -278,8 +278,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);
+@@ -308,8 +313,9 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
+ use_privsep ? " [net]" : "");
+ authctxt->service = xstrdup(service);
+ authctxt->style = style ? xstrdup(style) : NULL;
++ authctxt->role = role ? xstrdup(role) : NULL;
+ if (use_privsep)
+- mm_inform_authserv(service, style);
++ mm_inform_authserv(service, style, role);
+ userauth_banner(ssh);
+ if (auth2_setup_methods_lists(authctxt) != 0)
+ ssh_packet_disconnect(ssh,
+diff --git a/monitor.c b/monitor.c
+index 5f7df9539..769eda640 100644
+--- a/monitor.c
++++ b/monitor.c
+@@ -117,6 +117,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 *);
+@@ -195,6 +196,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
+@@ -815,6 +817,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
+@@ -848,15 +851,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);
+ }
+
+@@ -1578,7 +1608,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 2b1a2d590..4d87284aa 100644
+--- a/monitor.h
++++ b/monitor.h
+@@ -65,6 +65,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 a4b66c56f..6fb47becb 100644
+--- a/monitor_wrap.c
++++ b/monitor_wrap.c
+@@ -375,10 +375,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;
+@@ -388,7 +388,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);
+@@ -396,6 +397,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 830fdb308..c84f96d0c 100644
+--- a/monitor_wrap.h
++++ b/monitor_wrap.h
+@@ -48,7 +48,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 77cb8213a..3a59ba1b7 100644
+--- a/openbsd-compat/port-linux.c
++++ b/openbsd-compat/port-linux.c
+@@ -56,7 +56,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;
+@@ -70,9 +70,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) {
+@@ -102,7 +109,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;
+
+@@ -111,7 +118,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:
+@@ -133,7 +140,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;
+@@ -143,7 +150,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 3c22a854d..c88129428 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 4fe8744ee..70c3a9b58 100644
+--- a/platform.c
++++ b/platform.c
+@@ -144,7 +144,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)
+ /*
+@@ -185,7 +185,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 7fef8c983..027fdfb51 100644
+--- a/platform.h
++++ b/platform.h
+@@ -25,7 +25,7 @@ void platform_post_fork_parent(pid_t child_pid);
+ void platform_post_fork_child(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 96960f2da..492463529 100644
+--- a/session.c
++++ b/session.c
+@@ -1355,7 +1355,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;
+
+@@ -1383,7 +1383,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) {
+@@ -1527,7 +1527,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);
+@@ -1545,7 +1545,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
+@@ -1941,7 +1941,7 @@ session_pty_req(struct ssh *ssh, Session *s)
+ sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
+
+ if (!use_privsep)
+- pty_setowner(s->pw, s->tty);
++ pty_setowner(s->pw, s->tty, s->authctxt->role);
+
+ /* Set window size from the packet. */
+ pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel);
+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.c b/sshd.c
+index 7944cf633..dd4a19131 100644
+--- a/sshd.c
++++ b/sshd.c
+@@ -584,7 +584,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
+ reseed_prngs();
+
+ /* Drop privileges */
+- do_setusercontext(authctxt->pw);
++ do_setusercontext(authctxt->pw, authctxt->role);
+
+ skip:
+ /* It is safe now to apply the key state */
+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);