I wanted to use rsync / ssh combination to do a backup of a phone that I don’t want to root. There were few problems:
a) the rsync4android failed with an error that said: ‘ssh: exiting: string is too long’:
b) other solutions meant being root.
I’ve decided to cross-compile openssh-5.8p2 (which came with my busybox) so that I can use it in a combination with rsync (which I’ve also cross compiled) and all controlled by GScript (this will be a topic of a separate post).
The troubles encountered with getting openssh to run are that there’s no luck for the getpw* methods in Android (as /etc/passwd
doesn’t exist and thus they return null. Just executing ssh on the phone produced the error: “You don’t exist, go away!”
I’ve tracked this down into ssh.c
file:
pw = getpwuid(original_real_uid); if (!pw) { logit("You don't exist, go away!"); exit(255); }
Just patching this line doesn’t work, since there will be segmentation faults and other calls to getpwuid
I’ve created a small patch that addresses this issue:
diff -rupN openssh-5.8p2-orig/misc.c openssh-5.8p2/misc.c --- openssh-5.8p2-orig/misc.c 2011-01-13 02:21:36.000000000 +0100 +++ openssh-5.8p2/misc.c 2015-05-03 13:21:07.488601303 +0200 @@ -533,7 +533,7 @@ tilde_expand_filename(const char *filena user[slash] = '\0'; if ((pw = getpwnam(user)) == NULL) fatal("tilde_expand_filename: No such user %s", user); - } else if ((pw = getpwuid(uid)) == NULL) /* ~/path */ + } else if ((pw = vi_getpwuid(uid)) == NULL) /* ~/path */ fatal("tilde_expand_filename: No such uid %ld", (long)uid); if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret)) @@ -996,3 +996,27 @@ sock_set_v6only(int s) error("setsockopt IPV6_V6ONLY: %s", strerror(errno)); #endif } + +/* + * viulian: since getpwuid fails on nonrooted phones (or roote + * but without /etc/passwd, let's replace it + */ +struct passwd* vi_getpwuid(uid_t uid) { + + struct passwd *pw = (struct passwd *)calloc(1, sizeof(struct passwd)); + if (!pw) { + logit("Not enough memory."); + exit(255); + } + + pw->pw_name = strdup("android"); + pw->pw_passwd = strdup("********"); + pw->pw_uid = getuid(); + pw->pw_gid = getgid(); + pw->pw_gecos = strdup("android"); + pw->pw_dir = strdup("/sdcard"); + pw->pw_shell = strdup("/system/bin/sh"); + + return pw; +} + diff -rupN openssh-5.8p2-orig/misc.h openssh-5.8p2/misc.h --- openssh-5.8p2-orig/misc.h 2010-12-01 01:50:35.000000000 +0100 +++ openssh-5.8p2/misc.h 2015-05-03 12:45:31.284430274 +0200 @@ -102,4 +102,6 @@ char *read_passphrase(const char *, int) int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2))); int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *); +struct passwd* vi_getpwuid(uid_t); + #endif /* _MISC_H */ diff -rupN openssh-5.8p2-orig/ssh.c openssh-5.8p2/ssh.c --- openssh-5.8p2-orig/ssh.c 2011-02-04 01:42:15.000000000 +0100 +++ openssh-5.8p2/ssh.c 2015-05-03 12:42:42.134518990 +0200 @@ -268,7 +268,7 @@ main(int ac, char **av) } #endif /* Get user data. */ - pw = getpwuid(original_real_uid); + pw = vi_getpwuid(original_real_uid); if (!pw) { logit("You don't exist, go away!"); exit(255); @@ -1481,7 +1481,7 @@ load_public_identity_files(void) xfree(keys); } #endif /* ENABLE_PKCS11 */ - if ((pw = getpwuid(original_real_uid)) == NULL) + if ((pw = vi_getpwuid(original_real_uid)) == NULL) fatal("load_public_identity_files: getpwuid failed"); pwname = xstrdup(pw->pw_name); pwdir = xstrdup(pw->pw_dir);
What it does is that it introduces a fake getpwuid
method (called vi_getpwuid
) which returns a valid passwd
struct but filled with fake data (I haven’t investigated the security risks linked to this – I just wanted to get the code running). It assumes the username is ‘android’ (the username is in fact the application id, but I haven’t studied how to retrieve that from the NDK layer).
It also assumes the user home dir to be /sdcard (where ssh will create the .ssh/known_hosts
file.
By trial and error, I found 3 places where the changes had to be done to get ssh to work via rsync: there were two checks in ssh.c
file and one more in misc.c
itself inside the tilde_expand_filename
method. This too had to be fixed, otherwise ssh would complain with:
tilde_expand_filename: No such uid 11041
Hope this helps!
k007sam
THANK YOU MAN! I SPENT ALMOST FUCKING 2 DAYS ON THIS SHIT! THANK YOU SO MUCH. SO WIERD Android SSH 8.0 works and 9.0 fails due to this problem.