summaryrefslogtreecommitdiff
path: root/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'session.c')
-rw-r--r--session.c85
1 files changed, 81 insertions, 4 deletions
diff --git a/session.c b/session.c
index f2cf52006..2d0958d11 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.307 2018/10/04 00:10:11 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,78 @@ 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#ifdef SIGINFO
2124 if (strcmp(name, "INFO@openssh.com") == 0)
2125 return SIGINFO;
2126#endif
2127 return -1;
2128}
2129
2130static int
2131session_signal_req(struct ssh *ssh, Session *s)
2132{
2133 char *signame = NULL;
2134 int r, sig, success = 0;
2135
2136 if ((r = sshpkt_get_cstring(ssh, &signame, NULL)) != 0 ||
2137 (r = sshpkt_get_end(ssh)) != 0) {
2138 error("%s: parse packet: %s", __func__, ssh_err(r));
2139 goto out;
2140 }
2141 if ((sig = name2sig(signame)) == -1) {
2142 error("%s: unsupported signal \"%s\"", __func__, signame);
2143 goto out;
2144 }
2145 if (s->pid <= 0) {
2146 error("%s: no pid for session %d", __func__, s->self);
2147 goto out;
2148 }
2149 if (s->forced || s->is_subsystem) {
2150 error("%s: refusing to send signal %s to %s session", __func__,
2151 signame, s->forced ? "forced-command" : "subsystem");
2152 goto out;
2153 }
2154 if (!use_privsep || mm_is_monitor()) {
2155 error("%s: session signalling requires privilege separation",
2156 __func__);
2157 goto out;
2158 }
2159
2160 debug("%s: signal %s, killpg(%ld, %d)", __func__, signame,
2161 (long)s->pid, sig);
2162 temporarily_use_uid(s->pw);
2163 r = killpg(s->pid, sig);
2164 restore_uid();
2165 if (r != 0) {
2166 error("%s: killpg(%ld, %d): %s", __func__, (long)s->pid,
2167 sig, strerror(errno));
2168 goto out;
2169 }
2170
2171 /* success */
2172 success = 1;
2173 out:
2174 free(signame);
2175 return success;
2176}
2177
2104static int 2178static int
2105session_auth_agent_req(struct ssh *ssh, Session *s) 2179session_auth_agent_req(struct ssh *ssh, Session *s)
2106{ 2180{
@@ -2157,6 +2231,8 @@ session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype)
2157 success = session_window_change_req(ssh, s); 2231 success = session_window_change_req(ssh, s);
2158 } else if (strcmp(rtype, "break") == 0) { 2232 } else if (strcmp(rtype, "break") == 0) {
2159 success = session_break_req(ssh, s); 2233 success = session_break_req(ssh, s);
2234 } else if (strcmp(rtype, "signal") == 0) {
2235 success = session_signal_req(ssh, s);
2160 } 2236 }
2161 2237
2162 return success; 2238 return success;
@@ -2186,13 +2262,13 @@ void
2186session_pty_cleanup2(Session *s) 2262session_pty_cleanup2(Session *s)
2187{ 2263{
2188 if (s == NULL) { 2264 if (s == NULL) {
2189 error("session_pty_cleanup: no session"); 2265 error("%s: no session", __func__);
2190 return; 2266 return;
2191 } 2267 }
2192 if (s->ttyfd == -1) 2268 if (s->ttyfd == -1)
2193 return; 2269 return;
2194 2270
2195 debug("session_pty_cleanup: session %d release %s", s->self, s->tty); 2271 debug("%s: session %d release %s", __func__, s->self, s->tty);
2196 2272
2197 /* Record that the user has logged out. */ 2273 /* Record that the user has logged out. */
2198 if (s->pid != 0) 2274 if (s->pid != 0)
@@ -2403,7 +2479,8 @@ session_close_by_channel(struct ssh *ssh, int id, void *arg)
2403 } 2479 }
2404 debug("%s: channel %d child %ld", __func__, id, (long)s->pid); 2480 debug("%s: channel %d child %ld", __func__, id, (long)s->pid);
2405 if (s->pid != 0) { 2481 if (s->pid != 0) {
2406 debug("%s: channel %d: has child", __func__, id); 2482 debug("%s: channel %d: has child, ttyfd %d",
2483 __func__, id, s->ttyfd);
2407 /* 2484 /*
2408 * delay detach of session, but release pty, since 2485 * delay detach of session, but release pty, since
2409 * the fd's to the child are already closed 2486 * the fd's to the child are already closed