summaryrefslogtreecommitdiffhomepage
path: root/svr-chansession.c
diff options
context:
space:
mode:
Diffstat (limited to 'svr-chansession.c')
-rw-r--r--svr-chansession.c161
1 files changed, 29 insertions, 132 deletions
diff --git a/svr-chansession.c b/svr-chansession.c
index 7cedb8e..060a235 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -47,7 +47,7 @@ static int sessionsignal(struct ChanSess *chansess);
static int noptycommand(struct Channel *channel, struct ChanSess *chansess);
static int ptycommand(struct Channel *channel, struct ChanSess *chansess);
static int sessionwinchange(struct ChanSess *chansess);
-static void execchild(struct ChanSess *chansess);
+static void execchild(void *user_data_chansess);
static void addchildpid(struct ChanSess *chansess, pid_t pid);
static void sesssigchild_handler(int val);
static void closechansess(struct Channel *channel);
@@ -633,100 +633,37 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
* pty.
* Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
static int noptycommand(struct Channel *channel, struct ChanSess *chansess) {
-
- int infds[2];
- int outfds[2];
- int errfds[2];
- pid_t pid;
- unsigned int i;
+ int ret;
TRACE(("enter noptycommand"))
+ ret = spawn_command(execchild, chansess,
+ &channel->writefd, &channel->readfd, &channel->errfd,
+ &chansess->pid);
- /* redirect stdin/stdout/stderr */
- if (pipe(infds) != 0)
- return DROPBEAR_FAILURE;
- if (pipe(outfds) != 0)
- return DROPBEAR_FAILURE;
- if (pipe(errfds) != 0)
- return DROPBEAR_FAILURE;
-
-#ifdef __uClinux__
- pid = vfork();
-#else
- pid = fork();
-#endif
-
- if (pid < 0)
- return DROPBEAR_FAILURE;
-
- if (!pid) {
- /* child */
-
- TRACE(("back to normal sigchld"))
- /* Revert to normal sigchld handling */
- if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) {
- dropbear_exit("signal() error");
- }
-
- /* redirect stdin/stdout */
-#define FDIN 0
-#define FDOUT 1
- if ((dup2(infds[FDIN], STDIN_FILENO) < 0) ||
- (dup2(outfds[FDOUT], STDOUT_FILENO) < 0) ||
- (dup2(errfds[FDOUT], STDERR_FILENO) < 0)) {
- TRACE(("leave noptycommand: error redirecting FDs"))
- return DROPBEAR_FAILURE;
- }
-
- close(infds[FDOUT]);
- close(infds[FDIN]);
- close(outfds[FDIN]);
- close(outfds[FDOUT]);
- close(errfds[FDIN]);
- close(errfds[FDOUT]);
-
- execchild(chansess);
- /* not reached */
+ if (ret == DROPBEAR_FAILURE) {
+ return ret;
+ }
- } else {
- /* parent */
- TRACE(("continue noptycommand: parent"))
- chansess->pid = pid;
- TRACE(("child pid is %d", pid))
+ ses.maxfd = MAX(ses.maxfd, channel->writefd);
+ ses.maxfd = MAX(ses.maxfd, channel->readfd);
+ ses.maxfd = MAX(ses.maxfd, channel->errfd);
- addchildpid(chansess, pid);
+ addchildpid(chansess, chansess->pid);
- if (svr_ses.lastexit.exitpid != -1) {
- TRACE(("parent side: lastexitpid is %d", svr_ses.lastexit.exitpid))
- /* The child probably exited and the signal handler triggered
- * possibly before we got around to adding the childpid. So we fill
- * out its data manually */
- for (i = 0; i < svr_ses.childpidsize; i++) {
- if (svr_ses.childpids[i].pid == svr_ses.lastexit.exitpid) {
- TRACE(("found match for lastexitpid"))
- svr_ses.childpids[i].chansess->exit = svr_ses.lastexit;
- svr_ses.lastexit.exitpid = -1;
- }
+ if (svr_ses.lastexit.exitpid != -1) {
+ TRACE(("parent side: lastexitpid is %d", svr_ses.lastexit.exitpid))
+ /* The child probably exited and the signal handler triggered
+ * possibly before we got around to adding the childpid. So we fill
+ * out its data manually */
+ int i;
+ for (i = 0; i < svr_ses.childpidsize; i++) {
+ if (svr_ses.childpids[i].pid == svr_ses.lastexit.exitpid) {
+ TRACE(("found match for lastexitpid"))
+ svr_ses.childpids[i].chansess->exit = svr_ses.lastexit;
+ svr_ses.lastexit.exitpid = -1;
}
}
-
- close(infds[FDIN]);
- close(outfds[FDOUT]);
- close(errfds[FDOUT]);
- channel->writefd = infds[FDOUT];
- channel->readfd = outfds[FDIN];
- channel->errfd = errfds[FDIN];
- ses.maxfd = MAX(ses.maxfd, channel->writefd);
- ses.maxfd = MAX(ses.maxfd, channel->readfd);
- ses.maxfd = MAX(ses.maxfd, channel->errfd);
-
- setnonblocking(channel->readfd);
- setnonblocking(channel->writefd);
- setnonblocking(channel->errfd);
-
}
-#undef FDIN
-#undef FDOUT
TRACE(("leave noptycommand"))
return DROPBEAR_SUCCESS;
@@ -871,12 +808,9 @@ static void addchildpid(struct ChanSess *chansess, pid_t pid) {
/* Clean up, drop to user privileges, set up the environment and execute
* the command/shell. This function does not return. */
-static void execchild(struct ChanSess *chansess) {
-
- char *argv[4];
- char * usershell = NULL;
- char * baseshell = NULL;
- unsigned int i;
+static void execchild(void *user_data) {
+ struct ChanSess *chansess = user_data;
+ char *usershell = NULL;
/* with uClinux we'll have vfork()ed, so don't want to overwrite the
* hostkey. can't think of a workaround to clear it */
@@ -889,12 +823,6 @@ static void execchild(struct ChanSess *chansess) {
reseedrandom();
#endif
- /* close file descriptors except stdin/stdout/stderr
- * Need to be sure FDs are closed here to avoid reading files as root */
- for (i = 3; i <= (unsigned int)ses.maxfd; i++) {
- m_close(i);
- }
-
/* clear environment */
/* if we're debugging using valgrind etc, we need to keep the LD_PRELOAD
* etc. This is hazardous, so should only be used for debugging. */
@@ -933,18 +861,11 @@ static void execchild(struct ChanSess *chansess) {
}
}
- /* an empty shell should be interpreted as "/bin/sh" */
- if (ses.authstate.pw_shell[0] == '\0') {
- usershell = "/bin/sh";
- } else {
- usershell = ses.authstate.pw_shell;
- }
-
/* set env vars */
addnewvar("USER", ses.authstate.pw_name);
addnewvar("LOGNAME", ses.authstate.pw_name);
addnewvar("HOME", ses.authstate.pw_dir);
- addnewvar("SHELL", usershell);
+ addnewvar("SHELL", get_user_shell());
if (chansess->term != NULL) {
addnewvar("TERM", chansess->term);
}
@@ -963,32 +884,8 @@ static void execchild(struct ChanSess *chansess) {
agentset(chansess);
#endif
- /* Re-enable SIGPIPE for the executed process */
- if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) {
- dropbear_exit("signal() error");
- }
-
- baseshell = basename(usershell);
-
- if (chansess->cmd != NULL) {
- argv[0] = baseshell;
- } else {
- /* a login shell should be "-bash" for "/bin/bash" etc */
- int len = strlen(baseshell) + 2; /* 2 for "-" */
- argv[0] = (char*)m_malloc(len);
- snprintf(argv[0], len, "-%s", baseshell);
- }
-
- if (chansess->cmd != NULL) {
- argv[1] = "-c";
- argv[2] = chansess->cmd;
- argv[3] = NULL;
- } else {
- /* construct a shell of the form "-bash" etc */
- argv[1] = NULL;
- }
-
- execv(usershell, argv);
+ usershell = m_strdup(get_user_shell());
+ run_shell_command(chansess->cmd, ses.maxfd, usershell);
/* only reached on error */
dropbear_exit("child failed");