userspace.patch 4.53 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
diff --git a/options.h b/options.h
index d309ab4..63048e1 100644
--- a/options.h
+++ b/options.h
@@ -287,6 +287,12 @@ be overridden at runtime with -I. 0 disables idle timeouts */
 /* The default path. This will often get replaced by the shell */
 #define DEFAULT_PATH "/usr/bin:/bin"
 
+/* The prefix of dropbear environment variable overriding. */
+#define DROPBEAR_OVERRIDE_PREFIX "DROPBEAR_OVERRIDE_"
+#define DROPBEAR_OVERRIDE_PASSWORD DROPBEAR_OVERRIDE_PREFIX "PASSWORD"
+#define DROPBEAR_OVERRIDE_HOME DROPBEAR_OVERRIDE_PREFIX "HOME"
+#define DROPBEAR_OVERRIDE_SHELL DROPBEAR_OVERRIDE_PREFIX "SHELL"
+
 /* Some other defines (that mostly should be left alone) are defined
  * in sysoptions.h */
 #include "sysoptions.h"
diff --git a/runopts.h b/runopts.h
index 83b5861..f8999b9 100644
--- a/runopts.h
+++ b/runopts.h
@@ -86,6 +86,15 @@ typedef struct svr_runopts {
 	int noauthpass;
 	int norootpass;
 
+#ifdef ENABLE_SINGLEUSER
+	int singleuser;
+	struct {
+		char *password;
+		char *home;
+		char *shell;
+	} singleuserenv;
+#endif /* ifdef ENABLE_SINGLEUSER */
+
 #ifdef ENABLE_SVR_REMOTETCPFWD
 	int noremotetcp;
 #endif
diff --git a/svr-auth.c b/svr-auth.c
index 87e3c5e..adb2e8b 100644
--- a/svr-auth.c
+++ b/svr-auth.c
@@ -126,6 +126,14 @@ void recv_msg_userauth_request() {
 
 	
 	username = buf_getstring(ses.payload, &userlen);
+#ifdef ENABLE_SINGLEUSER
+	/* If userspace enabled, ignore username */
+	if (svr_opts.singleuser) {
+		m_free(username);
+		/* Get the current login of the user running dropbear */
51
+		username = m_strdup(getpwuid(getuid())->pw_name);
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
+	}
+#endif /* ifdef ENABLE_SINGLEUSER */
 	servicename = buf_getstring(ses.payload, &servicelen);
 	methodname = buf_getstring(ses.payload, &methodlen);
 
@@ -228,6 +236,18 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
 			}
 			authclear();
 			fill_passwd(username);
+#ifdef ENABLE_SINGLEUSER
+			if (svr_opts.singleuser) {
+				if (svr_opts.singleuserenv.home != NULL) {
+					m_free(ses.authstate.pw_dir);
+					ses.authstate.pw_dir = m_strdup(svr_opts.singleuserenv.home);
+				}
+				if (svr_opts.singleuserenv.shell != NULL) {
+					m_free(ses.authstate.pw_shell);
+					ses.authstate.pw_shell = m_strdup(svr_opts.singleuserenv.shell);
+				}
+			}
+#endif /* ifdef ENABLE_SINGLEUSER */
 			ses.authstate.username = m_strdup(username);
 	}
 
diff --git a/svr-runopts.c b/svr-runopts.c
index 2e836d2..1c21d7c 100644
--- a/svr-runopts.c
+++ b/svr-runopts.c
@@ -83,6 +83,9 @@ static void printhelp(const char * progname) {
 					"-W <receive_window_buffer> (default %d, larger may be faster, max 1MB)\n"
 					"-K <keepalive>  (0 is never, default %d)\n"
 					"-I <idle_timeout>  (0 is never, default %d)\n"
+#ifdef ENABLE_SINGLEUSER
+					"-n		Enable the single user mode.\n"
+#endif /* ifdef ENABLE_SINGLEUSER */
 #ifdef DEBUG_TRACE
 					"-v		verbose (compiled with DEBUG_TRACE)\n"
 #endif
@@ -128,6 +131,12 @@ void svr_getopts(int argc, char ** argv) {
 #ifndef DISABLE_ZLIB
 	opts.enable_compress = 1;
 #endif
+#ifdef ENABLE_SINGLEUSER
+	svr_opts.singleuser = 0;
+	svr_opts.singleuserenv.password = NULL;
+	svr_opts.singleuserenv.home = NULL;
+	svr_opts.singleuserenv.shell = NULL;
+#endif /* ifdef ENABLE_SINGLEUSER */
 	/* not yet
 	opts.ipv4 = 1;
 	opts.ipv6 = 1;
@@ -242,6 +251,17 @@ void svr_getopts(int argc, char ** argv) {
 				case 'u':
 					/* backwards compatibility with old urandom option */
 					break;
+#ifdef ENABLE_SINGLEUSER
+				case 'n':
+#ifndef ENABLE_SINGLEUSER_ROOT
+					/* If current user is root */
+					if (getuid() == 0) {
+						dropbear_log(LOG_ERR, "Can't enable singleuser mode as root.");
+					}
+#endif /* ifndef ENABLE_SINGLEUSER_ROOT */
+					svr_opts.singleuser = 1;
+					break;
+#endif /* ifdef ENABLE_SINGLEUSER */
 #ifdef DEBUG_TRACE
 				case 'v':
 					debug_trace = 1;
@@ -313,6 +333,20 @@ void svr_getopts(int argc, char ** argv) {
 		}
 		opts.idle_timeout_secs = val;
 	}
+#ifdef ENABLE_SINGLEUSER
+	if (svr_opts.singleuser) {
+		dropbear_log(LOG_INFO, "Starting dropbear as single user mode.");
+		svr_opts.singleuserenv.password = getenv(DROPBEAR_OVERRIDE_PASSWORD);
+		svr_opts.singleuserenv.home = getenv(DROPBEAR_OVERRIDE_HOME);
+		if (svr_opts.singleuserenv.home != NULL) {
+			dropbear_log(LOG_INFO, "Single user home is '%s'", svr_opts.singleuserenv.home);
+		}
+		svr_opts.singleuserenv.shell = getenv(DROPBEAR_OVERRIDE_SHELL);
+		if (svr_opts.singleuserenv.shell != NULL) {
+			dropbear_log(LOG_INFO, "Single user shell is '%s'", svr_opts.singleuserenv.shell);
+		}
+	}
+#endif /* ifdef ENABLE_SINGLEUSER */
 }
 
 static void addportandaddress(char* spec) {