summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--common-session.c9
-rw-r--r--dbutil.c45
-rw-r--r--dbutil.h1
-rw-r--r--session.h1
-rw-r--r--svr-chansession.c49
5 files changed, 58 insertions, 47 deletions
diff --git a/common-session.c b/common-session.c
index 30c0a58..ea8b3f7 100644
--- a/common-session.c
+++ b/common-session.c
@@ -414,3 +414,12 @@ static long select_timeout() {
ret = MIN(opts.keepalive_secs, ret);
return ret;
}
+
+const char* get_user_shell() {
+ /* an empty shell should be interpreted as "/bin/sh" */
+ if (ses.authstate.pw_shell[0] == '\0') {
+ return "/bin/sh";
+ } else {
+ return ses.authstate.pw_shell;
+ }
+}
diff --git a/dbutil.c b/dbutil.c
index d10a651..2dcae6b 100644
--- a/dbutil.c
+++ b/dbutil.c
@@ -393,8 +393,7 @@ int connect_remote(const char* remotehost, const char* remoteport,
* and the pid. exec_fn is the function that will actually execute the child process,
* it will be run after the child has fork()ed, and is passed exec_data. */
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
- int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid)
-{
+ int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
int infds[2];
int outfds[2];
int errfds[2];
@@ -466,6 +465,48 @@ int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
}
}
+/* Runs a command with "sh -c". Will close FDs (except stdin/stdout/stderr) and
+ * re-enabled SIGPIPE. If cmd is NULL, will run a login shell.
+ */
+void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) {
+ char * argv[4];
+ char * baseshell = NULL;
+ unsigned int i;
+
+ baseshell = basename(usershell);
+
+ if (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 (cmd != NULL) {
+ argv[1] = "-c";
+ argv[2] = cmd;
+ argv[3] = NULL;
+ } else {
+ /* construct a shell of the form "-bash" etc */
+ argv[1] = NULL;
+ }
+
+ /* Re-enable SIGPIPE for the executed process */
+ if (signal(SIGPIPE, SIG_DFL) == SIG_ERR) {
+ dropbear_exit("signal() error");
+ }
+
+ /* 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 <= maxfd; i++) {
+ m_close(i);
+ }
+
+ execv(usershell, argv);
+}
+
/* Return a string representation of the socket address passed. The return
* value is allocated with malloc() */
unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) {
diff --git a/dbutil.h b/dbutil.h
index ca09b4a..a70ed46 100644
--- a/dbutil.h
+++ b/dbutil.h
@@ -51,6 +51,7 @@ int dropbear_listen(const char* address, const char* port,
int *socks, unsigned int sockcount, char **errstring, int *maxfd);
int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
int *writefd, int *readfd, int *errfd, pid_t *pid);
+void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell);
int connect_remote(const char* remotehost, const char* remoteport,
int nonblocking, char ** errstring);
char* getaddrhostname(struct sockaddr_storage * addr);
diff --git a/session.h b/session.h
index c6d6ef8..60c3422 100644
--- a/session.h
+++ b/session.h
@@ -47,6 +47,7 @@ void common_session_cleanup();
void session_identification();
void send_msg_ignore();
+const char* get_user_shell();
/* Server */
void svr_session(int sock, int childpipe, char *remotehost, char *addrstring);
diff --git a/svr-chansession.c b/svr-chansession.c
index 6c99e70..060a235 100644
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -809,12 +809,8 @@ 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(void *user_data) {
-
- char *argv[4];
- char * usershell = NULL;
- char * baseshell = NULL;
- unsigned int i;
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 */
@@ -827,12 +823,6 @@ static void execchild(void *user_data) {
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. */
@@ -871,18 +861,11 @@ static void execchild(void *user_data) {
}
}
- /* 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);
}
@@ -901,32 +884,8 @@ static void execchild(void *user_data) {
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");