I wanted to be able to used my phone to log into my MacBook. The catch? I do not want passwords enabled. This post covers what I did to achieve this goal.

Android does not store users in /etc/passwd so it is exceedingly difficult to add users for command line work. Home directories for the users that are available seem to default to / or /data. /data and the SD card survive OS updates, but only root can properly write to /data. In light of this, this solution is written such that root calls ssh to log into another box. The SD card is used to store a script that contains a convenience function so connections can be canned.

The solution in this post assumes a rooted phone with busybox. My phone is a Nexus 5 running Cyanogenmod 13. As written, this solution may need minor modifications to work other phones.

Software Versions

$ date -u "+%Y-%m-%d %H:%M:%S +0000"
2016-04-08 19:58:32 +0000
$ uname -vm
Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64
$ ex -s +'%s/<[^>].\{-}>//ge' +'%s/\s\+//e' +'%norm J' +'g/^$/d' +%p +q! /System/Library/CoreServices/SystemVersion.plist | grep -E 'ProductName|ProductVersion' | sed 's/^[^ ]* //g' | sed 'N; s/\n/ /g'
Mac OS X 10.11.4
$ adb shell "uname -a" # Nexus 5; Cyanogenmod CM-13.0-20160407-NIGHTLY; Android 6.0.1
Linux localhost 3.4.0-g9b167b4 #1 SMP PREEMPT Wed Apr 6 21:49:26 PDT 2016 armv7l

Disable Password Based SSH

SSH can be enabled on OSX by going to Preferences → Sharing and selecting Remote Login. Optionally allow access for all users.

Password login can be disabled by adding the following lines to /etc/ssh/sshd_config as root. Note that the file is sshd_config, not ssh_config.

/etc/ssh/sshd_config partial listing

# Disable Password Login
UsePam no
ChallengeResponseAuthentication no
PasswordAuthentication no
kbdInteractiveAuthentication no

Restart sshd as root after making any configuration changes.

launchctl unload  /System/Library/LaunchDaemons/ssh.plist
launchctl load -w /System/Library/LaunchDaemons/ssh.plist

Adding an SSH Key to a Rooted Android Device

Open a shell on your phone and switch to root.

adb shell
su

Define some variables. Change these if you want to customize your installation. Note that the /data partition survives OS updates.

SSH_HOME="/data/.ssh"
SSH_ID="${SSH_HOME}/id_rsa"

Create the .ssh directory.

mkdir "${SSH_HOME}"
chmod 700 "${SSH_HOME}"

Create a symlink so root ssh will work. The root home directory is /. This step will need to be repeated after an OS update.

mount -o remount,rw /
ln -s "${SSH_HOME}" /.ssh

Generate the SSH key.

ssh-keygen -t rsa -f "${SSH_ID}"

Add .ssh/known_hosts.

touch "${SSH_HOME}/known_hosts"
chmod 644 "${SSH_HOME}/known_hosts"

Copy the Android public key from the phone to to .ssh/authorized_keys on any machines you want to log into.

cat "${SSH_ID}.pub" 

As root on the Android phone, ssh into a machine to add it to .ssh/known_hosts.

ssh "username@host.org"

Convenience SSH Shell Script

Doing command line work with a tiny touch screen keyboard is painful. Convenience shell functions make this task bearable.

I could not get .profile to work out of the box on Android. The Android shell always runs /system/etc/mkshrc. The problem is that this script is replaced when the operating system is updated so the goal is to keep changes minimal. Remount /system in read/write mode so this file can be modified.

mount -o remount,rw /system

Add a line to load a script from the SD card to the bottom of mkshrc.

/system/etc/mkshrc partial listing

source /sdcard/workon.sh # new line

: place customisations above this line

Now the workon.sh script will be loaded from the SD card when the shell starts. Files on the SD card can not be executed, so loading the script makes more sense than creating a utility. If the script were placed in /data it could be executed, but only by root. This solution allows a non-root shell to use the script.

Add the following convenience function to /sdcard/workon.sh to log into different machines. Replace the alpha and beta entries with your own machines. This file should survive operating system updates because it is on the SD card.

Redefine SSH_ID if you want to store .ssh in another location. Note that ssh will refuse to use the keys if they are user readable, so putting them on the SD card is not an option.

/sdcard/workon.sh

#!/system/bin/env sh
workon() {
  SSH_USERNAME="username"
  SSH_ID="/data/.ssh/id_rsa"
  case "${1}" in
    admin)
      su -c "cd; clear; pwd"; su
      ;;
    alpha)
      su -c "ssh -i '${SSH_ID}' '${SSH_USERNAME}@alpha.org'"
      ;;
    beta)
      su -c "ssh -i '${SSH_ID}' '${SSH_USERNAME}@192.168.0.123'"
      ;;
    *)
      if [ -n "${1}" ]
      then
        su -c "ssh -i '${SSH_ID}' '${SSH_USERNAME}@${1-localhost}'"
      else
        cd; clear; pwd
      fi
      ;;
  esac
}

Now the Android phone can log into machine Alpha like this.

workon alpha

As a bonus, the following can be used to get ready to do admin work on the Android phone.

workon admin

If you want to add the same function to a normal UNIX box, the workon function looks like this. Put it in something like ${HOME}/.profile.

${HOME}/.profile partial listing

workon() {
  SSH_USERNAME="username"
  ROOT_HOME="/var/root"
  case "${1}" in
    admin)
      (cd "${ROOT_HOME}"; clear; pwd; su)
      ;;
    alpha)
      ssh "${SSH_USERNAME}@alpha.org"
      ;;
    beta)
      ssh "${SSH_USERNAME}@192.168.0.123"
      ;;
    *)
      if [ -n "${1}" ]
      then
        ssh "${SSH_USERNAME}@{1-localhost}"
      else
        cd; clear; pwd
      fi
      ;;
  esac
}

Upgrading

After upgrading the OS, a couple of the steps need to be repeated.

Recreate the .ssh symlink.

mount -o remount,rw /
ln -s "${SSH_HOME}" /.ssh

Remount /system.

mount -o remount,rw /system

Add the line to load the SD card script to the bottom of mkshrc.

/system/etc/mkshrc partial listing

source /sdcard/workon.sh # new line

: place customisations above this line

Alternatively, use the following script to perform the above tasks after upgrading Android.

enable-ssh-workon.sh

#!/system/bin/env sh

SSH_HOME="/data/.ssh"
printf "Linking '/.ssh' -> '${SSH_HOME}' ... "
mount -o remount,rw /
rm -f "/.ssh"
ln -s "${SSH_HOME}" "/.ssh"
echo "Done."

MKSHRC="/system/etc/mkshrc"
printf "Patching '${MKSHRC}' ... "
mount -o remount,rw /system
BODY=$(cat "${MKSHRC}")
ORIGINAL=": place customisations above this line"
PATCH=$(printf "source /sdcard/workon.sh\n\n${ORIGINAL}")
BODY=$(echo "${BODY/${PATCH}/${ORIGINAL}}")
BODY=$(echo "${BODY/${ORIGINAL}/${PATCH}}")
echo "${BODY}" > "${MKSHRC}"
echo "Done."

References: