Android移植之dropbear
1.需求
Android虽然提供了ADB,但还是没有ssh,scp等用起来顺手,所以想移植一个ssh的Server到开发板上去,因为android默认的代码有external/dropbear,所以决定移植dropbear而不是openssh;
2.思路
要实现ssh,scp必须要满足以下的条件:
A)必须要有网路,这个可以由wifi来保证;
B)必须要有一个Server来打开22号端口,这个是由dropbear来完成的;
C)必须要有一个scp在开发板上,这样才能实现scp的功能;
3.适用范围
以下的步骤只适用于平台开发者,在最终产品里面必须要拿掉这个功能;
测试环境:
硬件:pxa310;
Android:2.1
理论上在其它硬件和android版本也应该可以工作,也许需要做微调;
4.移植步骤
4.1dropbear,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.cfake-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 5c67988..ff482ce 100644
--- 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 header file. */
-/* #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
header file. */
-/* #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
header file. */
#define HAVE_LIMITS_H 1
@@ -164,7 +164,7
@@
#define HAVE_NETINET_IN_H 1
/* Define to 1 if you have the
header file. */
-/* #define
HAVE_NETINET_IN_SYSTM_H */
+#define
HAVE_NETINET_IN_SYSTM_H 1
/* Define to 1 if you have the
header file. */
#define HAVE_NETINET_TCP_H 1
@@ -203,7 +203,7
@@
#define HAVE_SETUTXENT 1
/* Define to 1 if you have the
header file. */
-/* #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 header file. */
-/* #define
HAVE_UTMPX_H */
+#define
HAVE_UTMPX_H 1
/* Define to 1 if you have the header file. */
#define HAVE_UTMP_H 1
diff --git
a/debug.h b/debug.h
index 175f3fc..d45b6c4 100644
--- 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 0533f24..632a694 100644
--- 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 5be1e2a..94a4316 100644
---
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 619a451..a62728b 100644
---
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里面,就可以实现开机启动了;
5.备注
注意这里面的改动是root用户输入任何密码都可以的,所以不能用于产品中;
如果还经常碰到:
sh:
scp: not found
而无法scp的话,请确保你已经在根目录建立了/bin/(或者/usr/bin)目录,并且把scp放到里面去了;
作者:wylhistory
联系方式:wylhistory@gmail.com