summaryrefslogtreecommitdiff
path: root/session.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2018-10-02 12:40:07 +0000
committerDamien Miller <djm@mindrot.org>2018-10-02 22:41:01 +1000
commitcd98925c6405e972dc9f211afc7e75e838abe81c (patch)
tree295a45cea9fce0ad18a8463d604e1fdce8246768 /session.c
parentdba50258333f2604a87848762af07ba2cc40407a (diff)
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
Diffstat (limited to 'session.c')
-rw-r--r--session.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/session.c b/session.c
index f2cf52006..63adc68c5 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.c,v 1.305 2018/07/25 13:56:23 deraadt Exp $ */ 1/* $OpenBSD: session.c,v 1.306 2018/10/02 12:40:07 djm Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -705,7 +705,9 @@ do_exec(struct ssh *ssh, Session *s, const char *command)
705 command = auth_opts->force_command; 705 command = auth_opts->force_command;
706 forced = "(key-option)"; 706 forced = "(key-option)";
707 } 707 }
708 s->forced = 0;
708 if (forced != NULL) { 709 if (forced != NULL) {
710 s->forced = 1;
709 if (IS_INTERNAL_SFTP(command)) { 711 if (IS_INTERNAL_SFTP(command)) {
710 s->is_subsystem = s->is_subsystem ? 712 s->is_subsystem = s->is_subsystem ?
711 SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR; 713 SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
@@ -2101,6 +2103,76 @@ session_env_req(struct ssh *ssh, Session *s)
2101 return (0); 2103 return (0);
2102} 2104}
2103 2105
2106/*
2107 * Conversion of signals from ssh channel request names.
2108 * Subset of signals from RFC 4254 section 6.10C, with SIGINFO as
2109 * local extension.
2110 */
2111static int
2112name2sig(char *name)
2113{
2114#define SSH_SIG(x) if (strcmp(name, #x) == 0) return SIG ## x
2115 SSH_SIG(HUP);
2116 SSH_SIG(INT);
2117 SSH_SIG(KILL);
2118 SSH_SIG(QUIT);
2119 SSH_SIG(TERM);
2120 SSH_SIG(USR1);
2121 SSH_SIG(USR2);
2122#undef SSH_SIG
2123 if (strcmp(name, "INFO@openssh.com") == 0)
2124 return SIGINFO;
2125 return -1;
2126}
2127
2128static int
2129session_signal_req(struct ssh *ssh, Session *s)
2130{
2131 char *signame = NULL;
2132 int r, sig, success = 0;
2133
2134 if ((r = sshpkt_get_cstring(ssh, &signame, NULL)) != 0 ||
2135 (r = sshpkt_get_end(ssh)) != 0) {
2136 error("%s: parse packet: %s", __func__, ssh_err(r));
2137 goto out;
2138 }
2139 if ((sig = name2sig(signame)) == -1) {
2140 error("%s: unsupported signal \"%s\"", __func__, signame);
2141 goto out;
2142 }
2143 if (s->pid <= 0) {
2144 error("%s: no pid for session %d", __func__, s->self);
2145 goto out;
2146 }
2147 if (s->forced || s->is_subsystem) {
2148 error("%s: refusing to send signal %s to %s session", __func__,
2149 signame, s->forced ? "forced-command" : "subsystem");
2150 goto out;
2151 }
2152 if (!use_privsep || mm_is_monitor()) {
2153 error("%s: session signalling requires privilege separation",
2154 __func__);
2155 goto out;
2156 }
2157
2158 debug("%s: signal %s, killpg(%ld, %d)", __func__, signame,
2159 (long)s->pid, sig);
2160 temporarily_use_uid(s->pw);
2161 r = killpg(s->pid, sig);
2162 restore_uid();
2163 if (r != 0) {
2164 error("%s: killpg(%ld, %d): %s", __func__, (long)s->pid,
2165 sig, strerror(errno));
2166 goto out;
2167 }
2168
2169 /* success */
2170 success = 1;
2171 out:
2172 free(signame);
2173 return success;
2174}
2175
2104static int 2176static int
2105session_auth_agent_req(struct ssh *ssh, Session *s) 2177session_auth_agent_req(struct ssh *ssh, Session *s)
2106{ 2178{
@@ -2157,6 +2229,8 @@ session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype)
2157 success = session_window_change_req(ssh, s); 2229 success = session_window_change_req(ssh, s);
2158 } else if (strcmp(rtype, "break") == 0) { 2230 } else if (strcmp(rtype, "break") == 0) {
2159 success = session_break_req(ssh, s); 2231 success = session_break_req(ssh, s);
2232 } else if (strcmp(rtype, "signal") == 0) {
2233 success = session_signal_req(ssh, s);
2160 } 2234 }
2161 2235
2162 return success; 2236 return success;