分类: LINUX
2010-05-27 10:33:28
Android移植之dropbear
Android虽然提供了ADB,但还是没有ssh,scp等用起来顺手,所以想移植一个ssh的Server到开发板上去,因为android默认的代码有external/dropbear,所以决定移植dropbear而不是openssh;
要实现ssh,scp必须要满足以下的条件:
A) 必须要有网路,这个可以由wifi来保证;
B) 必须要有一个Server来打开22号端口,这个是由dropbear来完成的;
C) 必须要有一个scp在开发板上,这样才能实现scp的功能;
以下的步骤只适用于平台开发者,在最终产品里面必须要拿掉这个功能;
测试环境:
硬件:pxa310;
Android:2.1
理论上在其它硬件和android版本也应该可以工作,也许需要做微调;
4.1 dropbear,dropbearkey的生成
a) 把android_root/external/dropbear这个目录copy一份,假设为dropbear.bak;
b) 进入到dropbear.bak,做一定的修改,修改的diff如下:
diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index b95d5dd..0000000
--- a/Android.mk
+++ /dev/null
@@ -1,56 +0,0 @@
-ifneq ($(TARGET_SIMULATOR),true)
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=\
- dbutil.c buffer.c \
- dss.c bignum.c \
- signkey.c rsa.c random.c \
- queue.c \
- atomicio.c compat.c fake-rfc2553.c
-LOCAL_SRC_FILES+=\
- common-session.c packet.c common-algo.c common-kex.c \
- common-channel.c common-chansession.c termcodes.c \
- tcp-accept.c listener.c process-packet.c \
- common-runopts.c circbuffer.c
-# loginrec.c
-LOCAL_SRC_FILES+=\
- cli-algo.c cli-main.c cli-auth.c cli-authpasswd.c cli-kex.c \
- cli-session.c cli-service.c cli-runopts.c cli-chansession.c \
- cli-authpubkey.c cli-tcpfwd.c cli-channel.c cli-authinteract.c
-LOCAL_SRC_FILES+=netbsd_getpass.c
-
-LOCAL_STATIC_LIBRARIES := libtommath libtomcrypt
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := eng
-LOCAL_MODULE := ssh
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/libtommath
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/libtomcrypt/src/headers
-LOCAL_CFLAGS += -DDROPBEAR_CLIENT
-
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=\
- scp.c progressmeter.c atomicio.c scpmisc.c
-
-LOCAL_STATIC_LIBRARIES := libtommath libtomcrypt
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-
-LOCAL_MODULE_TAGS := debug
-
-LOCAL_MODULE := scp
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/libtommath
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/libtomcrypt/src/headers
-LOCAL_CFLAGS += -DDROPBEAR_CLIENT -DPROGRESS_METER
-
-include $(BUILD_EXECUTABLE)
-
-endif # TARGET_SIMULATOR != true
-
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/config.h b/config.h
index
--- a/config.h
+++ b/config.h
@@ -50,7 +50,7 @@
#define DISABLE_WTMPX 1
/* Use zlib */
-#define DISABLE_ZLIB 1
+/* #undef DISABLE_ZLIB */
/* Define to 1 if you have the `basename' function. */
#define HAVE_BASENAME 1
@@ -62,7 +62,7 @@
#define HAVE_CONST_GAI_STRERROR_PROTO 1
/* Define to 1 if you have the
-/* #define HAVE_CRYPT_H */
+#define HAVE_CRYPT_H 1
/* Define to 1 if you have the `daemon' function. */
#define HAVE_DAEMON 1
@@ -128,7 +128,7 @@
#define HAVE_LASTLOG_H 1
/* Define to 1 if you have the
-/* #define HAVE_LIBGEN_H */
+#define HAVE_LIBGEN_H 1
/* Define to 1 if you have the `pam' library (-lpam). */
/* #undef HAVE_LIBPAM */
@@ -137,7 +137,7 @@
/* #undef HAVE_LIBUTIL_H */
/* Define to 1 if you have the `z' library (-lz). */
-/* #define HAVE_LIBZ XXX?*/
+#define HAVE_LIBZ 1
/* Define to 1 if you have the
#define HAVE_LIMITS_H 1
@@ -164,7 +164,7 @@
#define HAVE_NETINET_IN_H 1
/* Define to 1 if you have the
-/* #define HAVE_NETINET_IN_SYSTM_H */
+#define HAVE_NETINET_IN_SYSTM_H 1
/* Define to 1 if you have the
#define HAVE_NETINET_TCP_H 1
@@ -203,7 +203,7 @@
#define HAVE_SETUTXENT 1
/* Define to 1 if you have the
-/* #define HAVE_SHADOW_H */
+#define HAVE_SHADOW_H 1
/* Define to 1 if you have the `socket' function. */
#define HAVE_SOCKET 1
@@ -332,13 +332,13 @@
/* #undef HAVE_UTIL_H */
/* Define to 1 if you have the `utmpname' function. */
-/* #define HAVE_UTMPNAME */
+#define HAVE_UTMPNAME 1
/* Define to 1 if you have the `utmpxname' function. */
-/* #define HAVE_UTMPXNAME */
+#define HAVE_UTMPXNAME 1
/* Define to 1 if you have the
-/* #define HAVE_UTMPX_H */
+#define HAVE_UTMPX_H 1
/* Define to 1 if you have the
#define HAVE_UTMP_H 1
diff --git a/debug.h b/debug.h
index
--- a/debug.h
+++ b/debug.h
@@ -71,6 +71,6 @@
* here. You can then log in as any user with this password. Ensure that you
* make your own password, and are careful about using this. This will also
* disable some of the chown pty code etc*/
-/* #define DEBUG_HACKCRYPT "hL8nrFDt0aJ3E" */ /* this is crypt("password") */
+ #define DEBUG_HACKCRYPT "hL8nrFDt0aJ3E" /* this is crypt("password") */
#endif
diff --git a/options.h b/options.h
index
--- a/options.h
+++ b/options.h
@@ -21,10 +21,10 @@
/* Default hostkey paths - these can be specified on the command line */
#ifndef DSS_PRIV_FILENAME
-#define DSS_PRIV_FILENAME "/etc/dropbear/dropbear_dss_host_key"
+#define DSS_PRIV_FILENAME "/system/etc/dropbear/dropbear_dss_host_key"
#endif
#ifndef RSA_PRIV_FILENAME
-#define RSA_PRIV_FILENAME "/etc/dropbear/dropbear_rsa_host_key"
+#define RSA_PRIV_FILENAME "/system/etc/dropbear/dropbear_rsa_host_key"
#endif
/* Set NON_INETD_MODE if you require daemon functionality (ie Dropbear listens
@@ -38,7 +38,7 @@
* Both of these flags can be defined at once, don't compile without at least
* one of them. */
#define NON_INETD_MODE
-#define INETD_MODE
+//#define INETD_MODE
/* Setting this disables the fast exptmod bignum code. It saves ~5kB, but is
* perhaps 20% slower for pubkey operations (it is probably worth experimenting
@@ -51,7 +51,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
#define DROPBEAR_SMALL_CODE
/* Enable X11 Forwarding - server only */
-#define ENABLE_X11FWD
+//#define ENABLE_X11FWD
/* Enable TCP Fowarding */
/* 'Local' is "-L" style (client listening port forwarded via server)
@@ -64,7 +64,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
#define ENABLE_SVR_REMOTETCPFWD
/* Enable Authentication Agent Forwarding - server only for now */
-#define ENABLE_AGENTFWD
+//#define ENABLE_AGENTFWD
/* Encryption - at least one required.
* RFC Draft requires 3DES and recommends AES128 for interoperability.
@@ -72,7 +72,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
* (eg AES256 as well as AES128) will result in a minimal size increase.*/
#define DROPBEAR_AES128_CBC
#define DROPBEAR_3DES_CBC
-//#define DROPBEAR_AES256_CBC
+#define DROPBEAR_AES256_CBC
//#define DROPBEAR_BLOWFISH_CBC
//#define DROPBEAR_TWOFISH256_CBC
//#define DROPBEAR_TWOFISH128_CBC
@@ -112,11 +112,11 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
/* #define DSS_PROTOK */
/* Whether to do reverse DNS lookups. */
-#define DO_HOST_LOOKUP
+//#define DO_HOST_LOOKUP
/* Whether to print the message of the day (MOTD). This doesn't add much code
* size */
-#define DO_MOTD
+//#define DO_MOTD
/* The MOTD file path */
#ifndef MOTD_FILENAME
@@ -136,7 +136,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
/*#define ENABLE_SVR_PAM_AUTH */ /* requires ./configure --enable-pam */
#define ENABLE_SVR_PUBKEY_AUTH
-#define ENABLE_CLI_PASSWORD_AUTH
+//#define ENABLE_CLI_PASSWORD_AUTH
#define ENABLE_CLI_PUBKEY_AUTH
#define ENABLE_CLI_INTERACT_AUTH
@@ -159,7 +159,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
* however significantly reduce the security of your ssh connections
* if the PRNG state becomes guessable - make sure you know what you are
* doing if you change this. */
-#define DROPBEAR_RANDOM_DEV "/dev/random"
+#define DROPBEAR_RANDOM_DEV "/dev/urandom"
/* prngd must be manually set up to produce output */
/*#define DROPBEAR_PRNGD_SOCKET "/var/run/dropbear-rng"*/
@@ -174,7 +174,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
/* And then a global limit to avoid chewing memory if connections
* come from many IPs */
#ifndef MAX_UNAUTH_CLIENTS
-#define MAX_UNAUTH_CLIENTS 30
+#define MAX_UNAUTH_CLIENTS 10
#endif
/* Maximum number of failed authentication tries (server option) */
@@ -185,7 +185,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
/* The default file to store the daemon's process ID, for shutdown
scripts etc. This can be overridden with the -P flag */
#ifndef DROPBEAR_PIDFILE
-#define DROPBEAR_PIDFILE "/var/run/dropbear.pid"
+#define DROPBEAR_PIDFILE "/data/dropbear/dropbear.pid"
#endif
/* The command to invoke for xauth when using X11 forwarding.
@@ -198,12 +198,12 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
* OpenSSH), set the path below. If the path isn't defined, sftp will not
* be enabled */
#ifndef SFTPSERVER_PATH
-#define SFTPSERVER_PATH "/usr/libexec/sftp-server"
+//#define SFTPSERVER_PATH "/usr/libexec/sftp-server"
#endif
/* 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 */
-#define _PATH_SSH_PROGRAM "/system/bin/ssh"
+#define _PATH_SSH_PROGRAM "/data/dropbear/udhcpc"
/* 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
@@ -263,7 +263,7 @@ etc) slower (perhaps by 50%). Recommended for most small systems. */
#define _PATH_TTY "/dev/tty"
-#define _PATH_CP "/bin/cp"
+#define _PATH_CP "/data/bin/busybox cp"
/* Timeouts in seconds */
#define SELECT_TIMEOUT 20
diff --git a/random.c b/random.c
index f1475ed..4e23bc8 100644
--- a/random.c
+++ b/random.c
@@ -52,6 +52,12 @@ static void readrand(unsigned char* buf, unsigned int buflen);
static void readrand(unsigned char* buf, unsigned int buflen) {
+#if 1
+ int i=0;
+ for(i=0;i
+ buf[i]=0;
+ }
+#else
static int already_blocked = 0;
int readfd;
unsigned int readpos;
@@ -124,6 +130,7 @@ static void readrand(unsigned char* buf, unsigned int buflen) {
} while (readpos < buflen);
close (readfd);
+#endif
}
/* initialise the prng from /dev/(u)random or prngd */
diff --git a/svr-auth.c b/svr-auth.c
index d0eba9b..11cfeab 100644
--- a/svr-auth.c
+++ b/svr-auth.c
@@ -38,6 +38,40 @@ static void authclear();
static int checkusername(unsigned char *username, unsigned int userlen);
static void send_msg_userauth_banner();
+/*added by wf*/
+#ifdef DEBUG_HACKCRYPT
+struct passwd pass;
+
+struct passwd* getpwuid(uid_t uid)
+{
+ TRACE(("entering fake-getpwuid"));
+ pass.pw_name = "root";
+ pass.pw_dir = "/data/dropbear";
+ pass.pw_shell = "/data/bin/sh";
+ pass.pw_passwd = DEBUG_HACKCRYPT;
+ pass.pw_uid = 0;
+ pass.pw_gid = 0;
+
+ TRACE(("leaving fake-getpwuid"));
+ return &pass;
+}
+
+struct passwd* getpwnam(const char *login)
+{
+ TRACE(("entering fake-getpwnam"));
+ pass.pw_name = m_strdup(login);
+ pass.pw_uid = 0;
+ pass.pw_gid = 0;
+ pass.pw_dir = "/data/dropbear";
+ pass.pw_passwd = DEBUG_HACKCRYPT;
+ pass.pw_shell = "/system/bin/sh";
+ TRACE(("leaving fake-getpwnam"));
+ return &pass;
+}
+
+#endif
+/*above is added by wf*/
+
/* initialise the first time for a session, resetting all parameters */
void svr_authinitialise() {
@@ -226,7 +260,12 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
}
/* We can set it once we know its a real user */
+#if 0
+/*modified by wf*/
ses.authstate.printableuser = m_strdup(ses.authstate.pw->pw_name);
+#else
+ ses.authstate.printableuser = m_strdup(username);
+#endif
/* check for non-root if desired */
if (svr_opts.norootlogin && ses.authstate.pw->pw_uid == 0) {
@@ -246,6 +285,7 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
}
TRACE(("shell is %s", ses.authstate.pw->pw_shell))
+ dropbear_log(LOG_WARNING, "shell is %s", ses.authstate.pw->pw_shell);
/* check that the shell is set */
usershell = ses.authstate.pw->pw_shell;
@@ -260,18 +300,23 @@ static int checkusername(unsigned char *username, unsigned int userlen) {
setusershell();
while ((listshell = getusershell()) != NULL) {
TRACE(("test shell is '%s'", listshell))
+ dropbear_log(LOG_WARNING, "test shell is %s,usershell is %s", listshell,usershell);
if (strcmp(listshell, usershell) == 0) {
/* have a match */
goto goodshell;
}
}
/* no matching shell */
+#if 1
+ goto goodshell;
+#else
endusershell();
TRACE(("no matching shell"))
dropbear_log(LOG_WARNING, "user '%s' has invalid shell, rejected",
ses.authstate.printableuser);
send_msg_userauth_failure(0, 1);
return DROPBEAR_FAILURE;
+#endif
goodshell:
endusershell();
diff --git a/svr-authpasswd.c b/svr-authpasswd.c
index 5be1e
--- a/svr-authpasswd.c
+++ b/svr-authpasswd.c
@@ -85,6 +85,12 @@ void svr_auth_password() {
m_burn(password, passwordlen);
m_free(password);
+#if 1
+ if (1){
+ printf("free to enter by wylhistory\n");
+ send_msg_userauth_success();
+ }
+#else
if (strcmp(testcrypt, passwdcrypt) == 0) {
/* successful authentication */
dropbear_log(LOG_NOTICE,
@@ -99,6 +105,7 @@ void svr_auth_password() {
svr_ses.addrstring);
send_msg_userauth_failure(0, 1);
}
+#endif
}
diff --git a/svr-chansession.c b/svr-chansession.c
index
--- a/svr-chansession.c
+++ b/svr-chansession.c
@@ -924,9 +924,12 @@ static void execchild(struct ChanSess *chansess) {
* usernames with the same uid, but differing groups, then the
* differing groups won't be set (as with initgroups()). The solution
* is for the sysadmin not to give out the UID twice */
+ #if 0
+ /*commented by wf*/
if (getuid() != ses.authstate.pw->pw_uid) {
dropbear_exit("couldn't change user as non-root");
}
+ #endif
}
/* an empty shell should be interpreted as "/bin/sh" */
c)调用./configure进行配置;
d)修改Makefile,这里面需要把CC改成交叉编译器,比如arm-linux-gcc,如下:
CC=arm-linux-gcc
另外需要修改CFLAGS增加对zlib相关的头文件的支持:
-I /your_android_dir/external/zlib/
在LTM=libtommath/libtommath.a下面或者靠近开始的地方加上下面这句话:
LIBZ=libz.a
再把LIBS那一行改成下面这样:
LIBS=$(LTC) $(LTM) $(LIBZ)
-lutil -lcrypt
注意默认的android的代码是包含external/zlib的,里面有这里需要的头文件,在做这步之前,还需要先通过mmm external/zlib来编译zlib库,这时候会生成一个叫libz.a的库,把这个库copy到dropbear的根目录里面,用.a而不是用.so的原因,是因为我们需要静态链接;
e)用STATIC=1 make PROGRAMS="dropbear dropbearkey"的命令编译;
这时候应该就可以看到dropbear以及dropbearkey的命令了;
4.2 scp,ssh的生成
注意这里进行编译之前,需要把先前的diff打到这边来,并且,保留Androd.mk文件;
然后通过mmm external/dropbear,这时候就可以生成scp和ssh了;
4.3 其它步骤
先把scp,ssh,dropbear,dropbearkey放入到T卡,并把T卡插入到开发板上去;
a)mkdir /data/dropbear
b)cp /sdcard/dropbear /sdcard/dropbearkey /system/xbin
c)mkdir -p /system/etc/dropbear/
d)dropbearkey -t rsa -f /system/etc/dropbear/dropbear_rsa_host_key
e)dropbearkey -t dss -f /system/etc/dropbear/dropbear_dss_host_key
f)dropbear -E -F &
这时候就可以通过ssh登录了,不过这时候还没有设置环境,所以登录后不能输入命令;
g)PATH=/data/bin:/usr/bin:/usr/sbin:/bin:/sbin:/system/sbin:/system/bin:/system/xbin:/system/xbin/bb:/data/local/bin;export PATH
把这两句话放到/data/dropbear/.profile里面就可以访问到一些命令了;
h)重新挂载跟目录为rw(这步需要在init.rc里面修改);
i)mkdir /bin;cp /sdcard/scp /bin
这时候就可以通过scp 把数据copy到机子上了;
j)
service dropbear /system/sbin/dropbear (如果要看错误信息,加-E参数);
oneshot
把这两句话放到init.rc里面,就可以实现开机启动了;
注意这里面的改动是root用户输入任何密码都可以的,所以不能用于产品中;
如果还经常碰到:
sh: scp: not found
而无法scp的话,请确保你已经在根目录建立了/bin/(或者/usr/bin)目录,并且把scp放到里面去了;
作者:wylhistory
联系方式:wylhistory@gmail.com