diff --git a/NOTES b/NOTES index d4bf951..10190aa 100644 --- a/NOTES +++ b/NOTES @@ -72,7 +72,6 @@ it uses select(), I'm not sure how I would honor Thread.interrupt() or whatever. It's not guaranteed to interrupt select(), and I'm not keen on adding an arbitrary timeout/polling feature to it. -XXX - scp XXX - zlib XXX - rsync diff --git a/dropbear/dbutil.c b/dropbear/dbutil.c index 2acc53b..3297151 100644 --- a/dropbear/dbutil.c +++ b/dropbear/dbutil.c @@ -574,10 +574,27 @@ int spawn_command(void(*exec_fn)(void *user_data), void *exec_data, * 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 * argv[100]; char * baseshell = NULL; unsigned int i; + /* 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); + } + + if (cmd && !strncmp(cmd, "scp ", 4)) { + int argc = split_cmd(cmd, argv, sizeof argv/sizeof argv[0]); + scp_main(argc, argv); + exit(0); + } + baseshell = basename(usershell); if (cmd != NULL) { @@ -598,17 +615,6 @@ void run_shell_command(const char* cmd, unsigned int maxfd, char* usershell) { 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); } diff --git a/dropbear/options.h b/dropbear/options.h index 73df90f..e652b8d 100644 --- a/dropbear/options.h +++ b/dropbear/options.h @@ -267,7 +267,7 @@ much traffic. */ /* This is used by the scp binary when used as a client binary. If you're * not using the Dropbear client, you'll need to change it */ -#undef _PATH_SSH_PROGRAM +#define _PATH_SSH_PROGRAM "/dev/null" /* Whether to log commands executed by a client. This only logs the * (single) command sent to the server, not what a user did in a diff --git a/jni/Android.mk b/jni/Android.mk index d3b4bde..cc5f55e 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -449,6 +449,8 @@ DROPBEAR_SRCS := $(DROPBEAR_PATH)/atomicio.c \ $(DROPBEAR_PATH)/progressmeter.c \ $(DROPBEAR_PATH)/queue.c \ $(DROPBEAR_PATH)/rsa.c \ + $(DROPBEAR_PATH)/scp.c \ + $(DROPBEAR_PATH)/scpmisc.c \ $(DROPBEAR_PATH)/signkey.c \ $(DROPBEAR_PATH)/sshpty.c \ $(DROPBEAR_PATH)/svr-agentfwd.c \ diff --git a/jni/config.h b/jni/config.h index b7b360a..7d92f59 100644 --- a/jni/config.h +++ b/jni/config.h @@ -15,6 +15,7 @@ #define HAVE_GETADDRINFO 1 #define HAVE_FREEADDRINFO 1 #define HAVE_GETNAMEINFO 1 +#define HAVE_FORK 1 #define HAVE_BASENAME 1 #define HAVE_NETINET_TCP_H 1 @@ -26,13 +27,17 @@ #define DROPBEAR_SERVER 1 #define DBMULTI_dropbear 1 +#define DBMULTI_scp 1 #define DROPBEAR_MULTI 1 -extern const char *conf_path_file(const char *fn); /* in jni/interface.c */ +/* in jni/interface.c: */ extern const char *conf_path; extern const char *conf_shell; extern const char *conf_home; +const char *conf_path_file(const char *fn); +int split_cmd(const char *in, char **argv, int max_argc); + #endif /* __CONFIG_H__ */ diff --git a/jni/interface.c b/jni/interface.c index 510fb27..d31d0e9 100644 --- a/jni/interface.c +++ b/jni/interface.c @@ -54,8 +54,8 @@ jni_init(JNIEnv *env_) } /* split str into argv entries, honoring " and \ (but nothing else) */ -static int -process_extra(const char *in, char **argv, int max_argc) +int +split_cmd(const char *in, char **argv, int max_argc) { char curr[1000]; int curr_len = 0; @@ -63,6 +63,7 @@ process_extra(const char *in, char **argv, int max_argc) int argc = 0; if (!in) { + argv[argc] = NULL; return 0; } while (1) { @@ -71,7 +72,7 @@ process_extra(const char *in, char **argv, int max_argc) (!in_quotes && isspace(c))) { if (curr_len) { curr[curr_len] = 0; - if (argc+1 >= max_argc) { + if (argc+2 >= max_argc) { break; } argv[argc++] = strdup(curr); @@ -96,6 +97,7 @@ process_extra(const char *in, char **argv, int max_argc) curr[curr_len++] = c; } } + argv[argc] = NULL; return argc; } @@ -158,7 +160,7 @@ Java_org_galexander_sshd_SimpleSSHDService_start_1sshd(JNIEnv *env_, sprintf(argv[argc], "%d", (int)port); argc++; } - argc += process_extra(extra, &argv[argc], + argc += split_cmd(extra, &argv[argc], (sizeof argv / sizeof *argv) - argc); fprintf(stderr, "starting dropbear\n"); retval = dropbear_main(argc, argv);