Thursday, January 27, 2011

Enabling telnet and ftp access to the Kobo Wifi

This article is part of an extended series on Kobo development and investigation


Apparently I have to make this more obvious:

  • Take a backup of your Kobo's SD card before doing anything. If something doesn't work, you can't fix your Kobo without this backup. I will not send you a backup.
  • Any device hacking is risky. If you can't afford to break your device, leave now.

The Kobo Wifi has this handy 802.11 radio that it really only uses for online shopping. Not only is it calling out to be used for RSS feeds and web browsing, but it is also a really handy tool for developing on the device without having to crack it and solder serial port headers onto the board.

We can gain telnet and ftp access to the device quite trivially; see the pre-made KoboRoot.tgz patch linked to below for the really easy way. (WARNING: The premade patch is for an older Kobo Wifi firmware. See the comments for instructions and newer version info).

If you want to roll your own patch or you're using a different firmware revision, there isn't much to do. The Kobo already has busybox's telnetd, ftpd and inetd on it. All that's necessary is to:

  • Edit /etc/inittab and add the lines:
    ::sysinit:/etc/init.d/rcS2
    ::respawn:/usr/sbin/inetd -f /etc/inetd.conf.en
    
  • Create /etc/init.d/rcS2 with the content:
    #!/bin/sh
    mkdir -p /dev/pts
    mount -t devpts devpts /dev/pts
    /usr/sbin/inetd /etc/inetd.conf
    
    and run chmod a+x /etc/init.d/rcS2 to flag it executable.
  • create /etc/inetd.conf with the content:
    # service_name sock_type proto flags user server_path args
    21 stream  tcp     nowait  root    /bin/busybox ftpd -w -S  /
    23 stream tcp nowait root /bin/busybox telnetd -i
    
  • tar our new /etc into KoboRoot.tgz

(Edited for safer method suggested by tjm)

KoboRoot.tgz may then be used to update the device's operating system by putting it in the .kobo directory on the user-accessible flash.

Because it's not designed to be accessible from the outside world, the Kobo doesn't have any root password set. Telnet and FTP access as root will be offered with a blank password by default. You can change that once you telnet in if you like, by typing "passwd" at the root prompt. This won't affect the device's normal operations, only telnet/ftp access.

I created a canned KoboRoot.tgz (for firmware 1.7 ONLY) with these changes to save you the hassle of making them yourself. It was made from the initscripts in firmware release 1.7.4; if you use it with any other firmware and it fails to boot you'll have to do a factory reset. Because there are no binaries in the patch, only a modified /etc/init.d/rcS and a new /etc/inetd.conf, you can easily verify that the code isn't malicious. It has two optional features you can uncomment in /etc/init.d/rcS to (a) syslog to user flash for debugging, and (b) run a user-defined script from .kobo/rc.sh every boot. Both are commented out so they do nothing unless you edit the script to enable them.

Unlike modifying the boot splash screen, this is a pretty safe change as it's completely erased by a factory reset of the device.

22 comments:

  1. Thanks very much; it is good to have you working on the Kobo. What do you think of installing/enabling samba to enable wireless access to the SQL database etc?

    ReplyDelete
  2. If you add content via ftp, it is good to refresh the database to show it without having to to plug in and remove the USB, which triggers the necessary SQLite sync. The below (complete kludge of a) script mimics the USB trigger. It could be added to startup, in the way Craig outlines, so that a restart syncs, or run through telnet. Ultimately, it would be good to put it behind a key (although a script to enable WiFi with a button would be a higher priority IMV.)

    #!/bin/sh
    echo "\"adding\""
    SN=KBN647095B46990 ACTION=add /usr/local/Kobo/udev/usb
    echo "sleeping"
    sleep 10
    # (Prob superfluous)
    echo "\"removing\""
    ACTION=remove /usr/local/Kobo/udev/usb
    return 0

    ReplyDelete
  3. If you add content via ftp, it is good to refresh the database to show it without having to to plug in and remove the USB, which triggers the necessary SQLite sync. The below (complete kludge of a) script mimics the USB trigger. It could be added to startup, in the way Craig outlines, so that a restart syncs, or run through telnet. Ultimately, it would be good to put it behind a key (although a script to enable WiFi with a button would be a higher priority IMV.)

    #!/bin/sh
    echo "\"adding\""
    SN=KBN647095B46990 ACTION=add /usr/local/Kobo/udev/usb
    echo "sleeping"
    sleep 10
    # (Prob superfluous)
    echo "\"removing\""
    ACTION=remove /usr/local/Kobo/udev/usb
    return 0

    ReplyDelete
  4. Doh! Actually, "Wireless On" and "Wireless Off" are behind the "Shop" menu.

    ReplyDelete
  5. this is great stuff cant what is next. what would be nice is setting a button to fetch mail and have and email account configured with calibre

    ReplyDelete
  6. badtoys: I'm never going to work on a mail client for the Kobo. I never even considered it as something that might be useful. The display is too slow to make it nice to use, and the input system is way too clumsy to be worth using for email. In any case, 3G smartphones do it better than the Kobo could and are very widespread.

    ReplyDelete
  7. BloGollum: Thanks for that. I've been meaning to fake plug/unplug events through the nickel socket. You're faking plug/unplug events by calling the udev hook scripts, which is probably a better way to do it. Thanks.

    I'm not doing much more on the Kobo at this point, because the Nickel app's plugin interface is nearly useless and it'd take a bit of work writing a Qt widget/object tree dumper and signal introspector to even figure out how/if you can hook into the UI. Nickel wasn't designed to be extensible; the plugin interface is a toy and and afterthought. It doesn't help that the QWS driver for epson_broadsheet is statically linked into Nickel, so you can't really write stand-alone Qt programs for the Kobo unless you hijack Nickel's startup.

    It also seems like Nickel brings down the wifi before it invokes plugins via the easter egg ui, so even if you claim the poker or blackjack plugin's MIME types for your own plugin and go to the hassle of invoking it via the easter egg ui, wifi drops as soon as you run it. Grr!

    Most of the things I _really_ want to improve in the Kobo require that I have access to the source code for Nickel. It's not viable to add series support, "go to page", etc using dynamically loaded plugins and runtime introspection. I have a nice Android phone now so I have lost interest in implementing an RSS reader for the Kobo; I pretty much need Nickel code to get anywhere with a worthwhile amount of time investment now.

    At this point I'm too busy with my paying work to waste any more time on it, given that the Kobo guys have gone from helpful to non-responsive and there's no sign they'll open up the qws driver let alone provide a way to make Nickel extensible.

    ReplyDelete
  8. i did not want a full email client just just a way to send the books over the network just a check and download of epubs. with calibre you can setup automatic downloads for rss news witch puts it in epub then you can have it emailed to an address. im not a big programer but i have been using linux since 95 so i will see what i can do

    ReplyDelete
  9. badtoyz: Good idea. That makes sense. You could add d-bus notifications to Fickel (the wifi monitor daemon) so you could automatically download feeds whenever wifi was turned on.

    The trouble is actually downloading the mailbox, with proper support for POP3+TLS, IMAP+TLS, etc.

    If the Kobo shipped a Java virtual machine I could put something like that together very quickly using the JavaMail APIs. Unfortunately, I'm not aware of any similar convenient, self-contained and reliable IMAP/POP3 libraries for C/C++. Sun/Oracle are being bastards about supporting Java 2 SE on ARM (they want to sell Java ME), otherwise I'd probably just do that.

    Good luck!

    ReplyDelete
  10. It's probably safer and more resiliant to upgrades to modify inittab than to modify rcS. The default inittab is pretty much a clone of what busybox would do anyway by default. I added two entries:

    ::sysinit:/etc/init.d/rcS2
    ::respawn:/usr/sbin/inetd -f /etc/inetd.conf.en

    rcS2 just contains the lines that had been added to rcS, and rcS stays unmodified.

    Notice that I do not even overwrite inetd.conf; I use a separate file instead. Also, init will keep inetd running even if it gets killed for any reason.

    ReplyDelete
  11. Also, it's incredibly unsafe to do this. I prefer ssh. To do this, I have installed dropbear on mine instead:

    Grab dropbear from maemo:

    http://maemo.org/packages/view/dropbear/

    I used the "diablo Extras free armel" version (0.52-2).

    Extract:

    mkdir d
    cd d
    ar x ../dropbear*.deb data.tar.gz
    tar xzf data.tar.gz


    Create KoboRoot.tgz and transfer to ereader (or ftp and untar manually if you already set up telnet/ftp):

    mkdir .ssh
    <create an RSA key for yourself if you don't already have one>
    # ssh-keygen -t rsa -b 2048
    <cat an RSA public key into .ssh/authorized_keys>
    # ssh-keygen -y -f ~/.ssh/id_rsa >.ssh/authorized_keys
    tar czf KoboRoot.tgz usr/{bin,lib,sbin} .ssh


    Finish it on the kobo (requires telnet or use of startup script hack):
    telnet <kobo.ip>
    -or-
    make ereader:.kobo/rc.sh on vfat be:

    mkdir -p /etc/dropbear
    cd /etc/dropbear
    test -f rsa_host_key || dropbearkey -t rsa -f rsa_host_key
    test -f dss_host_key || dropbearkey -t dss -f dss_host_key
    if ! grep -l dropbear /etc/inittab; then
    # note this is one line!
    echo '::respawn:/usr/sbin/dropbear -d /etc/dropbear/dss_host_key -r /etc/dropbear/rsa_host_key -F -s' >>/etc/inittab
    fi
    # change root's password to unusable
    # this will disable telnet/ftp access as root, but there are ways
    # to reenable if absolutely necessary
    sed -i 's/^root::/root:x:/' /etc/passwd
    sync
    # signal init to reread inittab
    kill -1 1


    You should now be able to ssh and scp to your kobo, using keys. The -s option to dropbear disables password access in any case. If you also want sftp access, you'll have to install sftp-server from openssh. From maemo again:

    http://maemo.org/packages/view/openssh-server/

    Extract as before, and move usr/lib/openssh/sftp-server into /usr/lib on your kobo (via scp or by adding it to the KoboRoot.tgz before transferring. Make sure and don't accidentally just transfer usr/lib/sftp-server, since it's just a soft link to openssh/sftp-server.

    ReplyDelete
    Replies
    1. I followed this guide and got ssh on my kobo but it just tells me:
      Permission denied (publickey).
      Correct me if i wrong but from reading here http://a3nm.net/blog/fnacbook_kobo_hacking.html#fnacbook_kobo_hacking_dropbear
      it seems i needed to "set root's home to /root in /etc/passwd to get key authentication working."
      However now i have no telnet and thus no access at all.

      How do i reenable telnet? Unless theres a better way?
      Thanks.

      Delete
  12. One final note: The rescan procedure seems to be simply:

    echo usb plug remove >>/tmp/nickel-hardware-status

    Since you can execute commands with ssh directly, it's pretty easy to execute a script containing that line right after copying into remote:/mnt/onboard.

    ReplyDelete
  13. tjm: good point re using inittab to launch inetd. Thanks. I'd tried that earlier, but was having issues getting it going because I needed to mount /dev/pts. I didn't think of adding a second startup script to inittab to do that rather than tweaking rcS. Good idea, it's much safer.

    As for dropbear - I generally detest telnet, but I didn't particularly care for a device as simple and dumb as a Kobo, especially since wifi is practically never turned on anyway. I wanted to provide instructions that involved minimal change to the device and no additional binaries. Certainly if I had a use case that called for wifi to actually be turned on and in use on networks I don't trust then I'd want to be using ssh.

    Thanks for your helpful comments.

    ReplyDelete
  14. hi craig/tjm

    i got the telnet and ftp to work on 1.7.4 wifi reader. I got another 1.8.x reader and tried the same rcS change - but not the 1.8.x won't complete the book. I'm able to get it into the USB mode - but still could not get it to complete boot. Any suggestions on fixing my 1.8.x reader.

    Thanks.

    ReplyDelete
  15. water4u99: Factory reset your Kobo if you can't undo the changes manually.

    ReplyDelete
  16. Craig,

    I tried that but didn't work. After several hours w/the kobo tech support, still not working. The Borders store where I purchased the kobo wifi from was kind enough to replace it. The firmware was updated to 1.9. I used the inittab technique from tjm. Success! Able to telnet in. Really appreciate both yours and tjm's help/posts.

    ReplyDelete
  17. BTW I used a very minimal setup.

    /etc/inittab

    ::sysinit:/etc/init.d/rcS2
    ::respawn:/usr/sbin/inetd -f /etc/inetd.conf.mine

    /etc/inetd.conf.mine

    21 stream tcp nowait root /bin/busybox ftpd -w -S /
    23 stream tcp nowait root /bin/busybox telnetd -i

    /etc/init.d/rcS2

    mkdir -p /dev/pts
    mount -t devpts devpts /dev/pts

    Note, I did not call the master /etc/initd.conf

    ReplyDelete
  18. Actually - you might want to ignore my earlier posts. Looks like version 1.9 has the telnet and ftp service already spec'd in the inetd.conf file.

    ReplyDelete
  19. Glad you got it sorted, though I'm very surprised a factory reset didn't do the trick. It erases the OS partition and rewrites it using the recovery partition, so it really should. Factory reset has always erased changes on mine when I messed it up while figuring things out.

    I very strongly advise you to make a backup disk image of your Kobo, so you can restore it if you have problems in the future. It was very kind of tech support to try to help you, because they would be entirely justified in saying "you broke it, too bad". Similarly, you're really lucky you were able to get it exchanged.

    ReplyDelete
  20. Re: Java VM

    Not sure what to make of it, but the CoolReader EB600 does have something that resembles a Java VM - JamVM.
    Perhaps mere fragments, but at least it contains a "working" executable (i.e. you can start it and it gives you a reply).
    Since I'm even more ignorant about Java than I am about Linux, I didn't yet manage to get something useful out of it.

    I didn't try to run it on the Kobo either, though, so perhaps it wouldn't even work.

    ReplyDelete
  21. tjm: thanks. Others please note you have to "plug it in" first (!) echo usb plug add >> /tmp/nickel-hardware-status. PS in my (now old) method the S/N is unique (on base of device)

    ReplyDelete