From cd98925c6405e972dc9f211afc7e75e838abe81c Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Tue, 2 Oct 2018 12:40:07 +0000 Subject: upstream: Add server support for signalling sessions via the SSH channel/ session protocol. Signalling is only supported to sesssions that are not subsystems and were not started with a forced command. Long requested in bz#1424 Based on a patch from markus@ and reworked by dtucker@; ok markus@ dtucker@ OpenBSD-Commit-ID: 4bea826f575862eaac569c4bedd1056a268be1c3 --- session.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) (limited to 'session.c') diff --git a/session.c b/session.c index f2cf52006..63adc68c5 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.305 2018/07/25 13:56:23 deraadt Exp $ */ +/* $OpenBSD: session.c,v 1.306 2018/10/02 12:40:07 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -705,7 +705,9 @@ do_exec(struct ssh *ssh, Session *s, const char *command) command = auth_opts->force_command; forced = "(key-option)"; } + s->forced = 0; if (forced != NULL) { + s->forced = 1; if (IS_INTERNAL_SFTP(command)) { s->is_subsystem = s->is_subsystem ? SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR; @@ -2101,6 +2103,76 @@ session_env_req(struct ssh *ssh, Session *s) return (0); } +/* + * Conversion of signals from ssh channel request names. + * Subset of signals from RFC 4254 section 6.10C, with SIGINFO as + * local extension. + */ +static int +name2sig(char *name) +{ +#define SSH_SIG(x) if (strcmp(name, #x) == 0) return SIG ## x + SSH_SIG(HUP); + SSH_SIG(INT); + SSH_SIG(KILL); + SSH_SIG(QUIT); + SSH_SIG(TERM); + SSH_SIG(USR1); + SSH_SIG(USR2); +#undef SSH_SIG + if (strcmp(name, "INFO@openssh.com") == 0) + return SIGINFO; + return -1; +} + +static int +session_signal_req(struct ssh *ssh, Session *s) +{ + char *signame = NULL; + int r, sig, success = 0; + + if ((r = sshpkt_get_cstring(ssh, &signame, NULL)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) { + error("%s: parse packet: %s", __func__, ssh_err(r)); + goto out; + } + if ((sig = name2sig(signame)) == -1) { + error("%s: unsupported signal \"%s\"", __func__, signame); + goto out; + } + if (s->pid <= 0) { + error("%s: no pid for session %d", __func__, s->self); + goto out; + } + if (s->forced || s->is_subsystem) { + error("%s: refusing to send signal %s to %s session", __func__, + signame, s->forced ? "forced-command" : "subsystem"); + goto out; + } + if (!use_privsep || mm_is_monitor()) { + error("%s: session signalling requires privilege separation", + __func__); + goto out; + } + + debug("%s: signal %s, killpg(%ld, %d)", __func__, signame, + (long)s->pid, sig); + temporarily_use_uid(s->pw); + r = killpg(s->pid, sig); + restore_uid(); + if (r != 0) { + error("%s: killpg(%ld, %d): %s", __func__, (long)s->pid, + sig, strerror(errno)); + goto out; + } + + /* success */ + success = 1; + out: + free(signame); + return success; +} + static int session_auth_agent_req(struct ssh *ssh, Session *s) { @@ -2157,6 +2229,8 @@ session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype) success = session_window_change_req(ssh, s); } else if (strcmp(rtype, "break") == 0) { success = session_break_req(ssh, s); + } else if (strcmp(rtype, "signal") == 0) { + success = session_signal_req(ssh, s); } return success; -- cgit v1.2.3 From ff3a411cae0b484274b7900ef52ff4dad3e12876 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Tue, 2 Oct 2018 22:49:40 +1000 Subject: only support SIGINFO on systems with SIGINFO --- session.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'session.c') diff --git a/session.c b/session.c index 63adc68c5..c5ca0556e 100644 --- a/session.c +++ b/session.c @@ -2120,8 +2120,10 @@ name2sig(char *name) SSH_SIG(USR1); SSH_SIG(USR2); #undef SSH_SIG +#ifdef SIGINFO if (strcmp(name, "INFO@openssh.com") == 0) return SIGINFO; +#endif return -1; } -- cgit v1.2.3 From f1dd179e122bdfdb7ca3072d9603607740efda05 Mon Sep 17 00:00:00 2001 From: "djm@openbsd.org" Date: Thu, 4 Oct 2018 00:10:11 +0000 Subject: upstream: include a little more information about the status and disposition of channel's extended (stderr) fd; makes debugging some things a bit easier. No behaviour change. OpenBSD-Commit-ID: 483eb6467dc7d5dbca8eb109c453e7a43075f7ce --- channels.c | 29 ++++++++++++++++++++++++++--- channels.h | 3 ++- nchan.c | 52 +++++++++++++++++++++++++++++++--------------------- session.c | 9 +++++---- 4 files changed, 64 insertions(+), 29 deletions(-) (limited to 'session.c') diff --git a/channels.c b/channels.c index e90f7fea9..bd68177b7 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.384 2018/07/27 12:03:17 markus Exp $ */ +/* $OpenBSD: channels.c,v 1.385 2018/10/04 00:10:11 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -799,6 +799,25 @@ channel_find_open(struct ssh *ssh) return -1; } +/* Returns the state of the channel's extended usage flag */ +const char * +channel_format_extended_usage(const Channel *c) +{ + if (c->efd == -1) + return "closed"; + + switch (c->extended_usage) { + case CHAN_EXTENDED_WRITE: + return "write"; + case CHAN_EXTENDED_READ: + return "read"; + case CHAN_EXTENDED_IGNORE: + return "ignore"; + default: + return "UNKNOWN"; + } +} + /* * Returns a message describing the currently open forwarded connections, * suitable for sending to the client. The message contains crlf pairs for @@ -845,13 +864,16 @@ channel_open_message(struct ssh *ssh) case SSH_CHANNEL_MUX_PROXY: case SSH_CHANNEL_MUX_CLIENT: if ((r = sshbuf_putf(buf, " #%d %.300s " - "(t%d %s%u i%u/%zu o%u/%zu fd %d/%d cc %d)\r\n", + "(t%d %s%u i%u/%zu o%u/%zu " + "fd %d/%d/%d [%s] sock %d cc %d)\r\n", c->self, c->remote_name, c->type, c->have_remote_id ? "r" : "nr", c->remote_id, c->istate, sshbuf_len(c->input), c->ostate, sshbuf_len(c->output), - c->rfd, c->wfd, c->ctl_chan)) != 0) + c->rfd, c->wfd, c->efd, + channel_format_extended_usage(c), + c->sock, c->ctl_chan)) != 0) fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r)); continue; @@ -2352,6 +2374,7 @@ channel_garbage_collect(struct ssh *ssh, Channel *c) if (c->detach_user != NULL) { if (!chan_is_dead(ssh, c, c->detach_close)) return; + debug2("channel %d: gc: notify user", c->self); c->detach_user(ssh, c->self, NULL); /* if we still have a callback */ diff --git a/channels.h b/channels.h index 1aeafe94e..aa2a87c10 100644 --- a/channels.h +++ b/channels.h @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.h,v 1.131 2018/06/06 18:22:41 djm Exp $ */ +/* $OpenBSD: channels.h,v 1.132 2018/10/04 00:10:11 djm Exp $ */ /* * Author: Tatu Ylonen @@ -285,6 +285,7 @@ void channel_output_poll(struct ssh *); int channel_not_very_much_buffered_data(struct ssh *); void channel_close_all(struct ssh *); int channel_still_open(struct ssh *); +const char *channel_format_extended_usage(const Channel *); char *channel_open_message(struct ssh *); int channel_find_open(struct ssh *); diff --git a/nchan.c b/nchan.c index 24929556d..da7a9d6d6 100644 --- a/nchan.c +++ b/nchan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nchan.c,v 1.67 2017/09/12 06:35:32 djm Exp $ */ +/* $OpenBSD: nchan.c,v 1.68 2018/10/04 00:10:11 djm Exp $ */ /* * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. * @@ -373,17 +373,23 @@ chan_shutdown_write(struct ssh *ssh, Channel *c) if (c->type == SSH_CHANNEL_LARVAL) return; /* shutdown failure is allowed if write failed already */ - debug2("channel %d: close_write", c->self); + debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])", + c->self, __func__, c->istate, c->ostate, c->sock, c->wfd, c->efd, + channel_format_extended_usage(c)); if (c->sock != -1) { - if (shutdown(c->sock, SHUT_WR) < 0) - debug2("channel %d: chan_shutdown_write: " - "shutdown() failed for fd %d: %.100s", - c->self, c->sock, strerror(errno)); + if (shutdown(c->sock, SHUT_WR) < 0) { + debug2("channel %d: %s: shutdown() failed for " + "fd %d [i%d o%d]: %.100s", c->self, __func__, + c->sock, c->istate, c->ostate, + strerror(errno)); + } } else { - if (channel_close_fd(ssh, &c->wfd) < 0) - logit("channel %d: chan_shutdown_write: " - "close() failed for fd %d: %.100s", - c->self, c->wfd, strerror(errno)); + if (channel_close_fd(ssh, &c->wfd) < 0) { + logit("channel %d: %s: close() failed for " + "fd %d [i%d o%d]: %.100s", + c->self, __func__, c->wfd, c->istate, c->ostate, + strerror(errno)); + } } } @@ -392,23 +398,27 @@ chan_shutdown_read(struct ssh *ssh, Channel *c) { if (c->type == SSH_CHANNEL_LARVAL) return; - debug2("channel %d: close_read", c->self); + debug2("channel %d: %s (i%d o%d sock %d wfd %d efd %d [%s])", + c->self, __func__, c->istate, c->ostate, c->sock, c->rfd, c->efd, + channel_format_extended_usage(c)); if (c->sock != -1) { /* * shutdown(sock, SHUT_READ) may return ENOTCONN if the * write side has been closed already. (bug on Linux) * HP-UX may return ENOTCONN also. */ - if (shutdown(c->sock, SHUT_RD) < 0 - && errno != ENOTCONN) - error("channel %d: chan_shutdown_read: " - "shutdown() failed for fd %d [i%d o%d]: %.100s", - c->self, c->sock, c->istate, c->ostate, - strerror(errno)); + if (shutdown(c->sock, SHUT_RD) < 0 && errno != ENOTCONN) { + error("channel %d: %s: shutdown() failed for " + "fd %d [i%d o%d]: %.100s", + c->self, __func__, c->sock, c->istate, c->ostate, + strerror(errno)); + } } else { - if (channel_close_fd(ssh, &c->rfd) < 0) - logit("channel %d: chan_shutdown_read: " - "close() failed for fd %d: %.100s", - c->self, c->rfd, strerror(errno)); + if (channel_close_fd(ssh, &c->rfd) < 0) { + logit("channel %d: %s: close() failed for " + "fd %d [i%d o%d]: %.100s", + c->self, __func__, c->rfd, c->istate, c->ostate, + strerror(errno)); + } } } diff --git a/session.c b/session.c index c5ca0556e..2d0958d11 100644 --- a/session.c +++ b/session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: session.c,v 1.306 2018/10/02 12:40:07 djm Exp $ */ +/* $OpenBSD: session.c,v 1.307 2018/10/04 00:10:11 djm Exp $ */ /* * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland * All rights reserved @@ -2262,13 +2262,13 @@ void session_pty_cleanup2(Session *s) { if (s == NULL) { - error("session_pty_cleanup: no session"); + error("%s: no session", __func__); return; } if (s->ttyfd == -1) return; - debug("session_pty_cleanup: session %d release %s", s->self, s->tty); + debug("%s: session %d release %s", __func__, s->self, s->tty); /* Record that the user has logged out. */ if (s->pid != 0) @@ -2479,7 +2479,8 @@ session_close_by_channel(struct ssh *ssh, int id, void *arg) } debug("%s: channel %d child %ld", __func__, id, (long)s->pid); if (s->pid != 0) { - debug("%s: channel %d: has child", __func__, id); + debug("%s: channel %d: has child, ttyfd %d", + __func__, id, s->ttyfd); /* * delay detach of session, but release pty, since * the fd's to the child are already closed -- cgit v1.2.3 From cf3f6ac19812e4d32874304b3854b055831c2124 Mon Sep 17 00:00:00 2001 From: Manoj Srivastava 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: 2018-08-24 Patch-Name: selinux-role.patch --- auth.h | 1 + auth2.c | 10 ++++++++-- monitor.c | 37 +++++++++++++++++++++++++++++++++---- 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(+), 32 deletions(-) (limited to 'session.c') diff --git a/auth.h b/auth.h index 977562f0a..90802a5eb 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 a77742819..3035926ba 100644 --- a/auth2.c +++ b/auth2.c @@ -257,7 +257,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) { Authctxt *authctxt = ssh->authctxt; Authmethod *m = NULL; - char *user, *service, *method, *style = NULL; + char *user, *service, *method, *style = NULL, *role = NULL; int authenticated = 0; double tstart = monotime_double(); @@ -270,8 +270,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++ == 0) { /* setup auth context */ @@ -298,8 +303,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(); if (auth2_setup_methods_lists(authctxt) != 0) packet_disconnect("no authentication methods enabled"); diff --git a/monitor.c b/monitor.c index eabc1e89b..08fddabd7 100644 --- a/monitor.c +++ b/monitor.c @@ -117,6 +117,7 @@ int mm_answer_sign(int, struct sshbuf *); int mm_answer_pwnamallow(int, struct sshbuf *); int mm_answer_auth2_read_banner(int, struct sshbuf *); int mm_answer_authserv(int, struct sshbuf *); +int mm_answer_authrole(int, struct sshbuf *); int mm_answer_authpassword(int, struct sshbuf *); int mm_answer_bsdauthquery(int, struct sshbuf *); int mm_answer_bsdauthrespond(int, struct sshbuf *); @@ -193,6 +194,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 @@ -817,6 +819,7 @@ mm_answer_pwnamallow(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 @@ -850,16 +853,42 @@ mm_answer_authserv(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("%s: buffer error: %s", __func__, ssh_err(r)); - debug3("%s: service=%s, style=%s", - __func__, authctxt->service, authctxt->style); + debug3("%s: service=%s, style=%s, role=%s", + __func__, 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(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); } @@ -1501,7 +1530,7 @@ mm_answer_pty(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 44fbed589..8f65e684d 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 monitor { diff --git a/monitor_wrap.c b/monitor_wrap.c index 1865a122a..fd4d7eb3b 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -369,10 +369,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; @@ -382,7 +382,8 @@ mm_inform_authserv(char *service, char *style) if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); 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("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m); @@ -390,6 +391,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 7f93144ff..79e78cc90 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -43,7 +43,8 @@ int mm_is_monitor(void); DH *mm_choose_dh(int, int, int); int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t, 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(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 622988822..3e6e07670 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 security_context_t -ssh_selinux_getctxbyname(char *pwname) +ssh_selinux_getctxbyname(char *pwname, const char *role) { security_context_t sc = NULL; char *sename = NULL, *lvl = NULL; @@ -71,9 +71,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) { @@ -103,7 +110,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) { security_context_t user_ctx = NULL; @@ -112,7 +119,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: @@ -134,7 +141,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) { security_context_t new_tty_ctx = NULL; security_context_t user_ctx = NULL; @@ -146,7 +153,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 41acc9370..35654ea51 100644 --- a/platform.c +++ b/platform.c @@ -142,7 +142,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) /* @@ -183,7 +183,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 ea4f9c584..60d72ffe7 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_sys_dir_uid(uid_t); diff --git a/session.c b/session.c index 2d0958d11..19f38637e 100644 --- a/session.c +++ b/session.c @@ -1380,7 +1380,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; @@ -1408,7 +1408,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) { @@ -1547,7 +1547,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); @@ -1565,7 +1565,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 @@ -1955,7 +1955,7 @@ session_pty_req(struct ssh *ssh, Session *s) ssh_tty_parse_modes(ssh, s->ttyfd); 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 ce59dabd9..675c91146 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 673db87f6..2bc6679e5 100644 --- a/sshd.c +++ b/sshd.c @@ -683,7 +683,7 @@ privsep_postauth(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 4da84d05f..676ade50e 100644 --- a/sshpty.c +++ b/sshpty.c @@ -162,7 +162,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; @@ -184,7 +184,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); -- cgit v1.2.3