mirror of
https://github.com/clearml/dropbear
synced 2025-02-07 13:21:15 +00:00
- Add run_shell_command() function to run a "sh -c" command, handling
lots of the work that exechild did (and can be shared by client -J option) --HG-- extra : convert_revision : a15dfd8017af8212b3b227f18ce2539dd471f7f6
This commit is contained in:
parent
7ac24b10b9
commit
12929e8cf0
@ -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;
|
||||
}
|
||||
}
|
||||
|
45
dbutil.c
45
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) {
|
||||
|
1
dbutil.h
1
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);
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user