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
This commit is contained in:
parent
dba5025833
commit
cd98925c64
76
session.c
76
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 <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
|
@ -705,7 +705,9 @@ do_exec(struct ssh *ssh, Session *s, const char *command)
|
||||||
command = auth_opts->force_command;
|
command = auth_opts->force_command;
|
||||||
forced = "(key-option)";
|
forced = "(key-option)";
|
||||||
}
|
}
|
||||||
|
s->forced = 0;
|
||||||
if (forced != NULL) {
|
if (forced != NULL) {
|
||||||
|
s->forced = 1;
|
||||||
if (IS_INTERNAL_SFTP(command)) {
|
if (IS_INTERNAL_SFTP(command)) {
|
||||||
s->is_subsystem = s->is_subsystem ?
|
s->is_subsystem = s->is_subsystem ?
|
||||||
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
|
SUBSYSTEM_INT_SFTP : SUBSYSTEM_INT_SFTP_ERROR;
|
||||||
|
@ -2101,6 +2103,76 @@ session_env_req(struct ssh *ssh, Session *s)
|
||||||
return (0);
|
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
|
static int
|
||||||
session_auth_agent_req(struct ssh *ssh, Session *s)
|
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);
|
success = session_window_change_req(ssh, s);
|
||||||
} else if (strcmp(rtype, "break") == 0) {
|
} else if (strcmp(rtype, "break") == 0) {
|
||||||
success = session_break_req(ssh, s);
|
success = session_break_req(ssh, s);
|
||||||
|
} else if (strcmp(rtype, "signal") == 0) {
|
||||||
|
success = session_signal_req(ssh, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: session.h,v 1.35 2017/09/12 06:32:07 djm Exp $ */
|
/* $OpenBSD: session.h,v 1.36 2018/10/02 12:40:07 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
|
@ -35,6 +35,7 @@ struct Session {
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
Authctxt *authctxt;
|
Authctxt *authctxt;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
int forced;
|
||||||
|
|
||||||
/* tty */
|
/* tty */
|
||||||
char *term;
|
char *term;
|
||||||
|
|
Loading…
Reference in New Issue