Discover a Linux Utility - xssstate

To learn more about Debian and Linux in general I'm selecting utilities at random from my PATH using the command below, learning what they do and writing a blog post about it. Previously: Part 1Part 2, Part 3

    $ (for folder in `echo $PATH | sed "s/:/\\n/g"`; do ls -1 $folder; done; ) | shuf -n 1 | xargs man

Today's utility is xssstate, which lets your check the status of X window system's screensaver. It's written by the suckless guys, who've created a number of very good tools, such as surf (a minimalist web browser) and dmenu (autocompleting program launcher), both of which I use regularly.

The utility itself is pretty simple, there are only four command line switches including -v, so this will be pretty short post. First we can check if the screensaver is currently enabled using -t switch:

    $ xssstate -s
    off

Obviously the screensaver is off, since I am actively using this computer - however if the screensaver was active it'd print "on" and if it was disabled altogether you'd see "disabled".

To check the time idle in milliseconds, use the -i switch:

    $ xssstate -i
    2
    $ sleep 5 && xssstate -i
    4947

And to get time in milliseconds until the screensaver activates, invoke it with -t:

    $ xssstate -t
    599998
    $ sleep 10 && xssstate -t
    590052

The way the utility does this is by using some functionality provided by a X11 library, wrapped in a handful of switch statements (they have their own neat little github-style source browser if you want to check out xssstate.c in its entirety):

    // ...
    info = XScreenSaverAllocInfo();
    XScreenSaverQueryInfo(dpy, DefaultRootWindow(dpy), info);

    if (showstate) {
    	switch(info->state) {
	case ScreenSaverOn:
		printf("on\n");
		break;
	case ScreenSaverOff:
		printf("off\n");
		break;
	case ScreenSaverDisabled:
		printf("disabled\n");
		break;
	}
    } else if (showtill) {
	switch(info->state) {
	case ScreenSaverOn:
		printf("0\n");
		break;
	case ScreenSaverOff:
		printf("%lu\n", info->til_or_since);
		break;
	case ScreenSaverDisabled:
		printf("-1\n");
		break;
	}
    } else if (showidle) {
	printf("%lu\n", info->idle);
    }
    // ...

When I do these articles I like to show some practical real-life usage of the utility - in this case I decided to add a little timer to my xmobar showing how long my computer had been idle. To this I added a Run Com entry to my xmobarrc:

    -- also stick %xssstate% into the template
    Run Com "xssstate" [ "-t" ] "xssstate" 10,

This ends up showing with something like the below - apologies for shaky-cam!

Discover a Linux Utility - slabtop

To learn more about Debian and Linux in general I'm selecting utilities at random from my PATH using the command below, learning what they do and writing a blog post about it. Previously: Part 1

    $ (for folder in `echo $PATH | sed "s/:/\\n/g"`; do ls -1 $folder; done; ) | shuf -n 1 | xargs man

Today's randomly selected utility is called slabtop - according to the man page it should "display kernel slab cache information in real time". I was pretty pleased about this one actually, I had no idea about slab allocators so it was good to have something to explore on a stormy day:

Put simply, Linux permits us to manage and allocate chunks of memory from a set of fixed-size buffers - called slabs - for different purposes. And slaptop gives us a view into the state of each slab cache: what they're called, how many elements are allocated in total and how full each slab is:

So for the highlighted row, we can know the following information:

- name ("kmalloc-32")

- number of slabs allocated (163)

- number of objects allocated (20007)

- percentage of slab space allocated (98%)

- total size of the slab space allocated (652K)

... and so on.

What is slab allocation

So what does all this mean and why do we need it? During the execution of some program we may have requested and released  lots of differently sized objects from the heap. This could result in a pretty fragmented heap.

This could mean that allocating new buffers is either a little slow or unpredictable, since we need to search for an appropriately sized buffer before we can mark it as allocated and return it to the calling code. If any part of our application depends on a particular object being allocated quickly and predictably this is not ideal. 

Slab allocation involves setting up a slab which can hold certain amount of objects of the same size and type. Since we're dealing with fixed-size objects allocating space for a new object is quick - we just need to scan through an array to find an unused slot, mark it as used, then calculate the address (start_addr + size * index) and return it.

We could roll our own implementation since it's pretty straightforward to implement - and that would be quite an interesting project for an evening or so. However if we're writing Linux kernel or module code there's already an existing set of functions which are well understood and battle-hardened. In addition these functions hide a lot of underlying complexity by abstracting a lot of the memory management (we can actually have numerous slabs, but Linux manages this for us).

How Linux supports slab allocation

To start with, if we want to create a new slab cache (a managed collection of slabs) we can use kmem_cache_create:

    struct kmem_cache *kmem_cache_create(
	    const char *,      // name of cache
	    size_t,            // size of each object
	    size_t,            // object alignment
	    unsigned long,     // any special flags
	    void (*)(void *)   // slab constructor
    );

To allocate a new object from this cache we can use kmem_cache_alloc:

    void *kmem_cache_alloc( 
    	struct kmem_cache *, // ptr to the cache 
    	gfp_t flags          // flags to use if we need new slab
    );

Then when we need to free any, kmem_cache_free which will mark the space as unused and make it available to the allocator:

    void kmem_cache_free(
    	struct kmem_cache *, // ptr to the cache
    	void *               // ptr to object to free
    );

And finally when we're done and we want to remove the cache entirely there is kmem_cache_destroy which will free and release all the slabs related to a given cache:

	void kmem_cache_destroy(
		struct kmem_cache *  // ptr to the cache
	);

How to use slab allocation

As an example of how this could be used we can think about it in the context of a simple kernel module. I'll roughly go over the individual parts, and then present a full-blown module to explore. Firstly we'll want to defined the type we want to create the slab cache for  - imaginatively named slabthing - and use it to declare a variable s:

    typedef struct
    {
      char foo; 
      char bar; 
      char baz;
    } slabthing;

    slabthing *s;

Inside our modules init_module we can use kmem_cache_create - so that our slab cache will be called "slabdemo", it'll allocate objects with the required size. Since I don't really care much about performance (specifying an appropriate alignment could permit us to use different/faster load instructions) so we'll just request it to be single byte-aligned.

    struct kmem_cache *slabthing_cache;

    int init_module(void)
    {
      slabthing_cache = kmem_cache_create("slabdemo", sizeof(slabthing), 1, NULL, NULL);
      // other module stuff...
    }

If our module wants to allocate space for the variable s in our cache we can call kmem_cache_alloc:

    s = kmem_cache_alloc(slabthing_cache, NULL);

When we want to free the cache, in this case in our module cleanup code, we can call kmem_cache_free and kmem_cache_destroy. I don't think the free is necessary in this case, but I've just included it anyway:

    void cleanup_module(void) {
        kmem_cache_free(slabthing_cache, s);
        kmem_cache_destroy(slabthing_cache);
     }

To see this in action I've created a little demo module that creates a cache and then allocates 128 objects when it's loaded - then frees all the objects and destroys them when it's unloaded. You'll need to make sure you have the sources checked out for your current kernel inside /usr/src/linux-<version>:

    $ git clone http://github.com/smcl/slabdemo
    $ cd slabdemo
    $ make 

If our module builds successfully we can load it using insmod and then fire up slabtop to see how things look:

    $ sudo insmod slabdemo.ko
    $ sudo slabtop

So there it is - our slabdemo cache is there, with 128 objects allocated in a single slab which can fit 240 objects in total (peculiar number!). If you check out slabtop you can easily see things like kmalloc-512, kmalloc-1024 and kmalloc-2048 which are probably slab caches used by kmalloc for allocating memory pools of 512, 1024 and 2048 bytes respectively. In any case, that's another issue for another day. Obviously this is a tool designed for kernel developers, or for sysadmins of particularly performance-critical sysadmins, but I'm glad I took the time to potter around with it.

Thinkpad X250 - Debian (cont'd)

After my original effort to get Debian to play nice on the X250 there were still a handful of things which weren't right. This mostly covers the remainder of the things that I had trouble with.

Automatically updating timezone based on location

I was recently in Vietnam and had to update my timezone manually - which was a minor inconvenience. There's an app called tzupdate which will attempt to determine your location and update the timezone accordingly whenever you run it. We can create a cron job to run tzupdate regularly to ensure the timezone is updated:

    $ sudo pip install -U tzupdate
    $ sudo crontab -e

enter the following - it'll cause tzupdate to run on the hour, every hour

    0 * * * * tzupdate

Two-fingered scroll left/right

When setting up my touchpad I neglected to setup the left/right scrolling - adding the followng line to /etc/X11/xorg.conf.d/50-synaptics.conf resolves this:

    Option "HorizTwoFingerScroll" "1"

For more info on the Synaptics touchpad driver, as always ArchLinux has some excellent documentation on the subject.

iPhone - Bluetooth and USB tethering 

Connecting over bluetooth is a little funny and can trouble you in unpredictable ways. Basically network manager overwrites /etc/resolv.conf when it connects/disconnects from a network and blueman doesn't touch it. So as you connect/disconnect from networks your bluetooth connection can be effectively useless as it'll be unable to resolve DNS queries (I'm guessing most people go to http://facebook.com and not http://31.13.76.68)

Easiest way is to prevent network manager from touching resolv.conf - and make sure you have a handful of good nameservers you can rely on. To do this edit /etc/NetworkManager/NetworkManager.conf and add the following to the [main] section:

    dns=none

Then add a handful of dns services to  /etc/resolv.conf:

    $ cat > /etc/resolv.conf << RESOLVEND
    #Google Public DNS
    nameserver 8.8.8.8
    nameserver 8.8.4.4
    
    # OpenDNS
    nameserver 208.67.222.222 
    nameserver 208.67.220.220
    RESOLVEND

Connecting over USB is a little easier

    $ sudo modprobe ipheth

If you're having trouble then apparently ipheth sometimes requires the iphone filesystem to be mounted - which means installing ifuse:

    $ sudo apt-get install libimobiledevice-dev libfuse-dev
    $ git clone https://github.com/libimobiledevice/ifuse
    $ cd ifuse/
    $ ./autogen.sh && ./configure && make && sudo make install
    $ mkdir ~/iPhone && sudo ifuse ~/iPhone

Thinkpad X250's Mobile Broadband setup (Vodafone CZ)

I had a bit of a nightmare of a time connecting to Vodafone using the builtin 4G modem. I think the main thing is that most places on the internet say that for pre-paid SIM you should set the APN to "ointernet" - when actually "internet" is correct. However I did find that I needed to set prefer_mbim to Y for the device:

    $ sudo echo "options cdc_ncm prefer_mbim=Y" >> /etc/modprobe.d/cdc_ncm.conf
You can either setup the connection using the NetworkManager UI and make it match the below:
... or manually create a file in /etc/NetworkManager/system-connections/ like the below:
    $ sudo cat /etc/NetworkManager/system-connections/Vodafone\ CZ
    [connection]
    id=Vodafone CZ
    uuid=2756323d-e364-49dc-9d86-92b8c2a44d15
    type=gsm
    autoconnect=false
    permissions=
    secondaries=

    [gsm]
    apn=internet
    number=*99***1#
    password-flags=1
    pin=1234

    [serial]
    baud=115200

    [ipv4]
    dns=8.8.8.8;
    dns-search=
    method=auto
 
    [ipv6]
    addr-gen-mode=stable-privacy
    dns-search=
    ip6-privacy=0
    method=auto

XTerm looks weird in XFCE

I've since moved nearly full-time to using Xmonad, but when I go back to XFCE and try to use xterm it has an extremely tiny font:

To make them appear a little nicer we need to edit ~/.Xresources - so that it looks like the below

Then fix up .Xresources:

    $ cat .Xresources 
    XTerm*faceName: Source Code Pro
    XTerm*faceSize: 10
    XTerm*metaSendsEscape: true
    ! Fonts {{{
    Xft.antialias: true
    Xft.hinting:   true
    Xft.rgba:      rgb
    Xft.hintstyle: hintfull
    Xft.dpi:       120
    ! }}}

After you restart X and relaunch an xterm everything should appear little nicer

Thinkpad X250 - SmartCards and GPG

This post describes setup and example usages of Smartcard with a Thinkpad's onboard reader and OpenPGP to handle keys for authentication and encryption. 

Your master key will be stored (securely I hope) on a USB drive and rarely used, with your Smart Card containing a couple of subkeys which will be used to sign and authenticate day-to-day.

At the end of the guide you should have a master key securely stored on a USB key, a hard-copy of revocation certificate,  some sub-keys stored on your Smart Card and some knowledge about how to use it to emails, and authenticate via ssh:

There are already very technical guides on how to set this up like the one on jclement.ca which steps 1-5 heavily lean on but even if you're pretty tech-savvy you may end up not 100% understanding exactly what you've actually done. 

I got my Smart Card by becoming a member of the EFSF fellowship or by picking up another OpenPGP smartcard (or a YubiKey if you don't have a reader, here).

Step 1. Securely create and boot from a Debian Live USB image

Download and verify a Debian live image per my previous guide here. We can now flash the USB key we're going to boot from:

    $ sudo dd bs=4M if=./debian-live-8.3.0-amd64-xfce-desktop+nonfree.iso of=/dev/sdb && sync
    272+0 records in
    272+0 records out
    1140850688 bytes (1.1 GB) copied, 214.052 s, 5.3 MB/s
Yes I used a very slow USB flash drive and it was rather painful.

Step 2. Setup the packages

Next couple of sections are pretty much the same steps as the jclement.ca guide - install gnupg2 and libraries we'll use:
    $ sudo apt-get install haveged gnupg2 gnupg-agent libpth20 pinentry-curses libccid pcscd scdaemon libksba8 paperkey opensc jpegoptim xloadimage
Change the configuration file for GnuPG so that it uses a different, stronger set of ciphers by default:
    $ mkdir ~/.gnupg
    $ cat > ~/.gnupg/gpg.conf << !
    no-emit-version
    no-comments
    keyid-format 0xlong
    with-fingerprint
    use-agent
    personal-cipher-preferences AES256 AES192 AES CAST5
    personal-digest-preferences SHA512 SHA384 SHA256 SHA224
    cert-digest-algo SHA512
    default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
    !

At this point jclement.ca advise that you disconnect from the network - which is probably a good idea since we're about to generate a handful of keys and we don't want anything to leak. 

What we're going to do is create a Master Key - which will be stored on a USB drive - and then use it to create a handful of Sub Keys which will be stored on the Smart Card for day-to-day use. Since the Sub Keys could conceivably be compromised we'll generate a revocation certificate which we can use to notify everyone that they should no longer be trusted - at this point we'd generate a new set of Sub Keys and load them onto our card.

Since there are a number of utilities and technologies you may not be familiar with I'm going to show a diagram at the end of each step in the key-creation process to help visualise what exactly is going on where. Here's a little diagram showing what symbols I'll be using.

Step 3. Creating the Master Key

    $ gpg2 --gen-key
    gpg (GnuPG) 2.0.26; Copyright (C) 2013 Free Software Foundation, Inc.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    
    gpg: keyring `/home/sean/.gnupg/secring.gpg' created
    gpg: keyring `/home/sean/.gnupg/pubring.gpg' created
    Please select what kind of key you want:
       (1) RSA and RSA (default)
       (2) DSA and Elgamal
       (3) DSA (sign only)
       (4) RSA (sign only)
    Your selection? 4
    RSA keys may be between 1024 and 4096 bits long.
    What keysize do you want? (2048) 4096
    Requested keysize is 4096 bits
    Please specify how long the key should be valid.
             0 = key does not expire
            = key expires in n days
          w = key expires in n weeks
          m = key expires in n months
          y = key expires in n years
    Key is valid for? (0) 0
    Key does not expire at all
    Is this correct? (y/N) y
    
    GnuPG needs to construct a user ID to identify your key.
    
    Real name: Sean McLemon
    Email address: sean.mclemon@gmail.com
    Comment: 
    You selected this USER-ID:
        "Sean McLemon "
    
    Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
    You need a Passphrase to protect your secret key.
    
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    gpg: /home/sean/.gnupg/trustdb.gpg: trustdb created
    gpg: key 0xC87419541EAC16A8 marked as ultimately trusted
    public and secret key created and signed.
    
    gpg: checking the trustdb
    gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
    gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
    pub   4096R/0xC87419541EAC16A8 2016-04-01
          Key fingerprint = D90B 2575 6FD3 D781 A856  9AE3 C874 1954 1EAC 16A8
    uid                 [ultimate] Sean McLemon 
    
    Note that this key cannot be used for encryption.  You may want to use
    the command "--edit-key" to generate a subkey for this purpose.

And add a pic:

    $ gpg2 --edit-key 0xC87419541EAC16A8
    gpg (GnuPG) 2.0.26; Copyright (C) 2013 Free Software Foundation, Inc.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    
    Secret key is available.
    
    pub  4096R/0xC87419541EAC16A8  created: 2016-04-01  expires: never       usage: SC  
                                   trust: ultimate      validity: ultimate
    [ultimate] (1). Sean McLemon 
    
    gpg> addphoto
    
    Pick an image to use for your photo ID.  The image must be a JPEG file.
    Remember that the image is stored within your public key.  If you use a
    very large picture, your key will become very large as well!
    Keeping the image close to 240x288 is a good size to use.
    
    Enter JPEG filename for photo ID: test.jpg
    Is this photo correct (y/N/q)? y
    
    You need a passphrase to unlock the secret key for
    user: "Sean McLemon "
    4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01
    
    
    pub  4096R/0xC87419541EAC16A8  created: 2016-04-01  expires: never       usage: SC  
                                   trust: ultimate      validity: ultimate
    [ultimate] (1). Sean McLemon 
    [ unknown] (2)  [jpeg image of size 746]
    
    gpg> save
So now we've got a Master Key our live distro's temporary filesystem. As I mentioned before this should only ever live on a USB key - to do anything useful we'll need to generate some Sub Keys.

Step 4. Creating the Sub Keys

A bit of a better explanation of Sub Keys is at https://wiki.debian.org/Subkeys. Remember, these are the keys we'll be using day-to-day and will be stored on our Smart Card.

    $ gpg2 --expert --edit-key 0xC87419541EAC16A8
    gpg (GnuPG) 2.0.26; Copyright (C) 2013 Free Software Foundation, Inc.
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.
    
    Secret key is available.
    
    gpg: checking the trustdb
    gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
    gpg: depth: 0  valid:   1  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 1u
    pub  4096R/0xC87419541EAC16A8  created: 2016-04-01  expires: never       usage: SC  
                                   trust: ultimate      validity: ultimate
    [ultimate] (1). Sean McLemon 
    [ultimate] (2)  [jpeg image of size 746]
    
    gpg> addkey
    Key is protected.
    
    You need a passphrase to unlock the secret key for
    user: "Sean McLemon "
    4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01
    
    Please select what kind of key you want:
       (3) DSA (sign only)
       (4) RSA (sign only)
       (5) Elgamal (encrypt only)
       (6) RSA (encrypt only)
       (7) DSA (set your own capabilities)
       (8) RSA (set your own capabilities)
    Your selection? 4
    RSA keys may be between 1024 and 4096 bits long.
    What keysize do you want? (2048) 2048
    Requested keysize is 2048 bits
    Please specify how long the key should be valid.
             0 = key does not expire
            = key expires in n days
          w = key expires in n weeks
          m = key expires in n months
          y = key expires in n years
    Key is valid for? (0) 6m
    Key expires at Wed 28 Sep 2016 21:41:58 CEST
    Is this correct? (y/N) y
    Really create? (y/N) y
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    
    pub  4096R/0xC87419541EAC16A8  created: 2016-04-01  expires: never       usage: SC  
                                   trust: ultimate      validity: ultimate
    sub  2048R/0x191900DBF062921B  created: 2016-04-01  expires: 2016-09-28  usage: S   
    [ultimate] (1). Sean McLemon 
    [ultimate] (2)  [jpeg image of size 746]
    
    gpg> addkey
    Key is protected.
    
    You need a passphrase to unlock the secret key for
    user: "Sean McLemon "
    4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01
    
    Please select what kind of key you want:
       (3) DSA (sign only)
       (4) RSA (sign only)
       (5) Elgamal (encrypt only)
       (6) RSA (encrypt only)
       (7) DSA (set your own capabilities)
       (8) RSA (set your own capabilities)
    Your selection? 6
    RSA keys may be between 1024 and 4096 bits long.
    What keysize do you want? (2048) 2048
    Requested keysize is 2048 bits
    Please specify how long the key should be valid.
             0 = key does not expire
            = key expires in n days
          w = key expires in n weeks
          m = key expires in n months
          y = key expires in n years
    Key is valid for? (0) 6m
    Key expires at Wed 28 Sep 2016 21:42:14 CEST
    Is this correct? (y/N) y
    Really create? (y/N) y
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    
    pub  4096R/0xC87419541EAC16A8  created: 2016-04-01  expires: never       usage: SC  
                                   trust: ultimate      validity: ultimate
    sub  2048R/0x191900DBF062921B  created: 2016-04-01  expires: 2016-09-28  usage: S   
    sub  2048R/0x46BDB50E980A2B9B  created: 2016-04-01  expires: 2016-09-28  usage: E   
    [ultimate] (1). Sean McLemon 
    [ultimate] (2)  [jpeg image of size 746]
    
    gpg> addkey
    Key is protected.
    
    You need a passphrase to unlock the secret key for
    user: "Sean McLemon "
    4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01
    
    Please select what kind of key you want:
       (3) DSA (sign only)
       (4) RSA (sign only)
       (5) Elgamal (encrypt only)
       (6) RSA (encrypt only)
       (7) DSA (set your own capabilities)
       (8) RSA (set your own capabilities)
    Your selection? 8
    
    Possible actions for a RSA key: Sign Encrypt Authenticate 
    Current allowed actions: Sign Encrypt 
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished
    
    Your selection? s
    
    Possible actions for a RSA key: Sign Encrypt Authenticate 
    Current allowed actions: Encrypt 
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished
    
    Your selection? e
    
    Possible actions for a RSA key: Sign Encrypt Authenticate 
    Current allowed actions: 
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished
    
    Your selection? a
    
    Possible actions for a RSA key: Sign Encrypt Authenticate 
    Current allowed actions: Authenticate 
    
       (S) Toggle the sign capability
       (E) Toggle the encrypt capability
       (A) Toggle the authenticate capability
       (Q) Finished
    
    Your selection? q
    RSA keys may be between 1024 and 4096 bits long.
    What keysize do you want? (2048) 
    Requested keysize is 2048 bits
    Please specify how long the key should be valid.
             0 = key does not expire
            = key expires in n days
          w = key expires in n weeks
          m = key expires in n months
          y = key expires in n years
    Key is valid for? (0) 6m
    Key expires at Wed 28 Sep 2016 21:42:43 CEST
    Is this correct? (y/N) y
    Really create? (y/N) y
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    
    pub  4096R/0xC87419541EAC16A8  created: 2016-04-01  expires: never       usage: SC  
                                   trust: ultimate      validity: ultimate
    sub  2048R/0x191900DBF062921B  created: 2016-04-01  expires: 2016-09-28  usage: S   
    sub  2048R/0x46BDB50E980A2B9B  created: 2016-04-01  expires: 2016-09-28  usage: E   
    sub  2048R/0xF1D25AD8AC008AA1  created: 2016-04-01  expires: 2016-09-28  usage: A   
    [ultimate] (1). Sean McLemon 
    [ultimate] (2)  [jpeg image of size 746]
    
    gpg> save

Now we've got the newly created Master and Sub-keys on the local filesystem. 

Step 5. Generate a revocation certificate

    $ gpg2 --gen-revoke 0xC87419541EAC16A8
    
    sec  4096R/0xC87419541EAC16A8 2016-04-01 Sean McLemon 
    
    Create a revocation certificate for this key? (y/N) y
    Please select the reason for the revocation:
      0 = No reason specified
      1 = Key has been compromised
      2 = Key is superseded
      3 = Key is no longer used
      Q = Cancel
    (Probably you want to select 1 here)
    Your decision? 1
    Enter an optional description; end it with an empty line:
    > FSB got hold of my private key
    > 
    Reason for revocation: Key has been compromised
    y
    Is this okay? (y/N) y
    
    You need a passphrase to unlock the secret key for
    user: "Sean McLemon "
    4096-bit RSA key, ID 0xC87419541EAC16A8, created 2016-04-01
    
    ASCII armored output forced.
    Revocation certificate created.
    
    Please move it to a medium which you can hide away; if Mallory gets
    access to this certificate he can use it to make your key unusable.
    It is smart to print this certificate and store it away, just in case
    your media become unreadable.  But have some caution:  The print system of
    your machine might store the data and make it available to others!
    -----BEGIN PGP PUBLIC KEY BLOCK-----
    Comment: A revocation certificate should follow
    
    iQIgBCABCgAKBQJW/s+XAx0CeQAKCRDIdBlUHqwWqEsbEACFj7ZDRgwcvG99F1Hb
    PHzqGPXh5X04nnjpPbnWaKviycvdCQtFT3N3Hg0c1fmgBBDMXHXKcP8dBwrsgmU0
    x1vEFUSmzvaW+s/EZXh8xwfXhGVmBG+H+i5JqfiPXelaKH12/pDPqIIE+jlwFx5O
    a+I3TMg5x5pBzpSWmCNmFgxU4jEJ6SBwsYYDCwGjStS3C8Dojk7RfJug/+wZAhk2
    nuGbHKeL48TmLwVsoqlbut57yUzqJ16wC9u46oOwKUeUnluEhOm8eT8fvQsHwM11
    THx8UshfjY1/2p5oA4e7GOyB93u7mS5+u57dkKiHwDbNKVq++rMnJH5nesgOT3f6
    D/5quHjQNUXwGJsxu3H+ZSxAmmj2q8ooaPZfDxeAqSgjLSu3vTQGK8HtsnJ3Cgu5
    tANW4SrDrqqvmpNzutGkmfLRgN/stSLi+MJz78h87nCDPQkMUmp6fEk2kEnVmj1B
    BEMY5SSrJrIDGwf4CGn4kzHDb9/GlS47x33LcE8g7F1lM1LQ7eNvRNpDU36dmiwj
    luJLtl0tKVW4YBz4Yo7AxmT0QYSCgXHWStt9XB1devps1CJ45dlbPNzAE8rJH2+1
    3YjZfFAgiSFFHMsq0C1M2+mQaqrAyGUVT/lR42Tok0GgwaZK48VWeP+cRZu07NDr
    pxodVfJ7TjcVUF04AEtSxayfbg==
    =ck5O
    -----END PGP PUBLIC KEY BLOCK-----
    
JClement suggests printing this out - if you do so it might want to create a QR code to make it easier to digitize. You might want avoid QR code generator sites since we're aiming for security, but you can generate one easily enough using python qrcode module:
    $ pip install qrcode
    Downloading/unpacking qrcode
      Downloading qrcode-5.2.2-py2.py3-none-any.whl (89kB): 89kB downloaded
    Requirement already satisfied (use --upgrade to upgrade): colorama in /usr/lib/python2.7/dist-packages (from qrcode)
    Requirement already satisfied (use --upgrade to upgrade): six in /usr/lib/python2.7/dist-packages (from qrcode)
    Installing collected packages: qrcode
    Successfully installed qrcode
    Cleaning up...
    $ python
    Python 2.7.9 (default, Mar  1 2015, 12:57:24) 
    [GCC 4.9.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import qrcode
    >>> cert = open("revoke_cert.asc")
    >>> cert_text = cert.read()
    >>> cert_qr = qrcode.make(cert_text)
    >>> cert_qr.save("revoke_cert.png")
The certificate itself is pretty sizeable, so the resulting QR code is pretty dense and you'll need a reasonable camera to successfully scan it (my iPhone 6S worked nicely). Using the lines above the resulting image will look a little like this - it's a little huge so I didn't want to include it in-line.

So assuming we've printed out revoke_cert.png and discarded the .asc file, at this point we should have created:

Step 6. Backup GPG and store keys on SD/USB

Now we've generated our keys we can copy them somewhere safe (an SD card, or USB)
    $ tar -czf gnupg.tgz ~/.gnupg
    tar: Removing leading `/' from member names
    $ gpg2 -a --export-secret-key 0xC87419541EAC16A8 >> 0xC87419541EAC16A8.master.key
    $ gpg2 -a --export-secret-subkeys 0xC87419541EAC16A8 >> 0xC87419541EAC16A8.subkeys.key
    $ gpg2 -a --export 0xC87419541EAC16A8 > 0xC87419541EAC16A8.public.key.asc
    $ sudo cp gnupg.tgz 0xC87419541EAC16A8.master.key 0xC87419541EAC16A8.subkeys.key 0xC87419541EAC16A8.public.key.asc /media/SDCARD/

Note - it is important to do this. Once we restart the filesystem of the live CD will no longer exist, and we'll lose all of our keys. then load the subkeys to the card.

Now we can distribute the key:

    $ gpg2 --keyserver hkp://pool.sks-keyservers.net --send-keys 0xC87419541EAC16A8
    gpg: sending key 0xC87419541EAC16A8 to hkp server pool.sks-keyservers.net

Now we can reboot, upload our public key to the internet and here's what we have - a master key stored offline/disconnected, a set of sub-keys on the smartcard we can use for everyday tasks, a printed certificate we can use to revoke our subkeys, and a public key somewhere on the net we can share with anyone we need to communicate securely with.

Step 7. Boot into usual OS + load keys

When you're sufficiently certain you've got a nice backup of the .gnupg directory, and the subkeys loaded to the card we can boot into our normal OS and remove the live USB card. 

We'll need to 

    $ gpg2 --import 0xC87419541EAC16A8.public.key.asc
    gpg: /home/sean/.gnupg/trustdb.gpg: trustdb created
    gpg: key C3969A6B: public key "Sean McLemon " imported
    gpg: Total number processed: 1
    gpg:               imported: 1  (RSA: 1)
Now everything is set - we explore a few situations where you might want to use a smart card.

Example 1. Signing/Encrypting a text file using your card

There's a very good guide produced by the Free Software Foundation @ https://emailselfdefense.fsf.org which you can follow if you want to use EnigMail and Thunderbird - if you want an easy way to sign/encrypt emails you should follow that. However if we just want to sign a message in a text file from the command line, we could do something like the below

    $ echo > msg << EOF
    > paddy schwartz party time
    > EOF
    $ gpg2 --output msg.sig --sign msg

Example 2. Decrypting a file using your card

If someone's sent you a file they'll encrypt it using your public key. You can use the keys stored on your card to decrypt it.

To set this up we'll first encrypt a simple text file using our own public key:

    $ echo "a funky test message" > plaintext.asc
    $ gpg2 --out cyphertext --recipient 0x2F3F79CDC3969A6B --encrypt plaintext.asc
    gpg: 720D24AD: There is no assurance this key belongs to the named user
    
    pub  2048R/720D24AD 2016-03-24 Sean McLemon 
     Primary key fingerprint: 63EB 6DF3 C42E 1AB3 92B5  BF02 2F3F 79CD C396 9A6B
          Subkey fingerprint: 3E3C 084E 622A BB06 EEFB  A739 A3FE 2BC1 720D 24AD

    It is NOT certain that the key belongs to the person named
    in the user ID.  If you *really* know what you are doing,
    you may answer the next question with yes.

    Use this key anyway? (y/N) y

OK now we'll verify that the card isn't connected, and that we cannot decrypt it without the card

    $ gpg2 --card-status
    gpg: selecting openpgp failed: Card not present
    gpg: OpenPGP card not available: Card not present
    $ gpg2 --out plaintext-decrypted.asc --decrypt cyphertext 
    gpg: selecting openpgp failed: Card not present
    gpg: encrypted with 2048-bit RSA key, ID 720D24AD, created 2016-03-24
          "Sean McLemon "
    gpg: public key decryption failed: Operation cancelled
    gpg: decryption failed: No secret key

Now if we insert the smart card and try to decrypt again we'll be prompted for our PIN, and the file will be decrypted successfully:

    $ gpg2 --out plaintext-decrypted.asc --decrypt cyphertext
    gpg: encrypted with 2048-bit RSA key, ID 720D24AD, created 2016-03-24
          "Sean McLemon "
    $ cat plaintext-decrypted.asc 
    a funky test message

Example 3. Authenticating with a remote machine using your card

    $ echo enable-ssh-support >> ~/.gnupg/gpg-agent.conf
    $ sudo emacs /etc/X11/Xsession.options # and comment/remove the line "use-ssh-agent"

Now we'll add our public key to the computer we want to connect to using ssh - in my case it's mokpo.local

    $ ssh-add -L | ssh mokpo.local 'cat >> ~/.ssh/authorized_keys'
and we can now test logging in

Example 4. Revoking your keys using the QR code

If our key is ever compromised and we'd like to revoke we will need to issue a revocation certificate to say that this key shouldn't ever be trusted. We can use the QR code we previously generated + printed out - first scan the QR code and save the results into a file revoke-certificate-qr.txt, and perform the following steps:

$ gpg2 --import revoke-certificate-qr.txt
$ gpg2 --keyserver hkp://pool.sks-keyservers.net --send-keys 0xC87419541EAC16A8

Now the world should know not to trust our old keypair, and we can go back to the start of this article and generate a completely new one - this time being extra careful to keep it safe!

Linux - networking without a UI using nmcli

The XMonad setup I described in this blog post should be functional and extendable enough to get started. However there is one glaring omission - no easy way to configure any wifi or 3G/4G networks you want to connect to. So it's useful to know a little about nmcli, the command-line interface to NetworkManager. This can also be useful if you're futzing around with a linux box remotely.

Fire up an xterm and run the following to check out which network interfaces you have available, and what state they are in:

    $ nmcli dev status
    DEVICE             TYPE      STATE            CONNECTION  
    cdc-wdm0           gsm       disconnected     -- 
    wlan0              wifi      disconnected     --
    F4:31:C3:30:E3:6F  bt        disconnected     --          
    eth0               ethernet  unavailable      --          
    lo                 loopback  unmanaged        --          

So we've five interfaces, none of which are connected to anything. I'll focus on the extremely common use-cases - connecting to open and secured wifi networks using the "wlan0" device, as well as connecting to 3G/4G networks using the "cdc/wdm0" device.

WiFi

To view available networks near you:

    $ nmcli dev wifi list
    *  SSID       MODE   CHAN  RATE       SIGNAL  BARS  SECURITY         
       Rotor bar  Infra  8     54 Mbit/s  72      ▂▄▆_                   
       ahnet      Infra  11    54 Mbit/s  42      ▂▄__  WEP              
       eduroam    Infra  1     54 Mbit/s  15      ▂___  WPA1 WPA2 802.1X 
       vakan      Infra  13    54 Mbit/s  12      ▂___  WEP              
       JAMU       Infra  1     54 Mbit/s  10      ▂___                   

If we want to connect to "Rotor bar" - an open, unsecured network, we can do the following

    $ nmcli device wifi connect "Rotor bar"
    Device 'wlan0' successfully activated with 'ccb0a5a1-ef8d-4fea-966f-7999f2611345'.

If this network was instead secured with the password "123456789" we would instead have used:

    $ nmcli dev wifi con "Rotor bar" password "123456789"

And when we want to disconnect from the WiFi, we can run:

    $ nmcli dev disconnect iface wlan0

And if we wanted to reconnect to this network:

    $ nmcli con up id "Rotor bar"

Mobile Broadband

We can check if you have already set up a Mobile Broadband (3G, LTE, etc seem to be appear as type "gsm") connection :
    $ nmcli connection show | grep gsm
    Vodafone CZ             2756323d-e364-49dc-9d86-92b8c2a44d15  gsm              --     

In my case I'd previously setup "Vodafone CZ" using the NetworkManager applet in XFCE, however if we want to do this in the CLI all we need to do is make sure a config file is present in the /etc/NetworkManager/system-connections folder which has the right setup

    $ sudo cat /etc/NetworkManager/system-connections/Vodafone\ CZ
    [connection]
    id=Vodafone CZ
    uuid=2756323d-e364-49dc-9d86-92b8c2a44d15
    type=gsm
    autoconnect=false
    permissions=
    secondaries=

    [gsm]
    apn=internet
    number=*99***1#
    password-flags=1
    pin=1234

    [serial]
    baud=115200

    [ipv4]
    dns=8.8.8.8;
    dns-search=
    method=auto
 
    [ipv6]
    addr-gen-mode=stable-privacy
    dns-search=
    ip6-privacy=0
    method=auto

So, assuming you're using Vodafone in the Czech Republic you can use this config, tweak the PIN as necessary (it's the SIM PIN, btw) rerun nmcli connection show to check NetworkManager knows about it, and then run the following to bring it up:

    $ nmcli connection up id "Vodafone CZ"
    Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/27)
And to disconnect
    $ nmcli connection down id "Vodafone CZ"
    Connection 'Vodafone CZ' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/27)

So there we have it - it's possible there's a strange configuration that you need, so you may have to dig into the nmcli man pages - but as long as you have some sort of internet connection I found the followingpages useful:

XMonad - quickstart and intro

XMonad is a minimalist Window Manager written in Haskell. There are plenty of pretty screenshots of various xmonad setups on the net, but as a newbie it's not clear how to use them or how to get started. Say you find yourself in the  XMonad/Config archive page and find a pretty looking screenshot like NNoel's (below):

You install XMonad, update your .xinitrc, restart X and this is what you actually see:

It's a little intimidating to be confronted with this, and it's really tough to know how to go from "I have a blank screen" to "check out my shiny desktop". There's no easy way to get to a Settings/Configuration menu to customise things, and clicking around achieves very little indeed. Even firing up a web browser to google for some guides isn't very obvious. 

I recently went through this whole process, and managed to piece together a nice simple xmonad config. This is a guide to how to go from blank screen to a setup like the below:

We've got a status bar which shows handy things like workspaces, info about any active network interfaces, the usual cpu/memory usage shenanigans, volume (from a slightly hacky script, more on that later) date and the weather where I am. Also the little Tux emoji in the corner is clickable - by default it saves a screenshot of the whole screen, but you can customise it pretty easily since it's just executing a command in the shell.

To get this sort of setup we first need to make sure a couple of fonts are installed - Source Code Pro and Font Awesome. You could just run the commands below, but if you want could find the latest release of Source Code Pro on this page in case there's any updates:

    $ curl -LO https://github.com/adobe-fonts/source-code-pro/archive/2.010R-ro/1.030R-it.tar.gz
    $ tar -xzf 1.030R-it.tar.gz
    $ git clone https://github.com/FortAwesome/Font-Awesome
    $ sudo cp source-code-pro-2.010R-ro-1.030R-it/TTF/*.ttf Font-Awesome/fonts/*.ttf /usr/share/fonts
    $ fc-cache -f -v

Now we can install the necessary packages that we need:

    $ sudo apt-get install xmonad xmonad-contrib xmobar dmenu cabal-install
    $ cabal install xmonad-extras

Finally we can pull down my xmonad config from github

    $ cd && git clone http://github.com/smcl/xmonad .xmonad

Now all the packages are installed, and the Xmonad config is all setup we can restart X and should see something like this

Still a blank screen, but now we have a little status bar. To start with we can bring up an xterm by hitting Windows-Shift-Return:

Obviously from xterm we can launch whatever app we want from here, like firefox:

We can close windows using either some app-specific functionality (Ctrl-Q in firefox, or typing "exit" in xterm), but you can also close the current selected window from XMonad by holding down Windows-Shift-C.

Launching your apps from an xterm could be a little inconvenient, and the terminal itself could fill up with diagnostic messages unless you remember to redirect stderr to /Dev/null each time. 're squeezed side-by-side it's not ideal, plus your xterm will fill up with all sorts of fun diagnostic messages. A better way to work is to launch them using dmenu - a program we installed earlier that let's us launch applications from within monad easily. To bring up dmenu hit Windows-P, if you start typing it'll attempt to autocomplete programs from your PATH:

I tend to use workspaces to organise my windows - so I'll have firefox running on its own in one, then a couple of xterms in another, emacs on its own somewhere else etc. To create a new workspace and switch to it press Windows-1, Windows-2 ... Windows-9. If you're in, say, workspace 1 and you want to move the current window to workspace 2 you can his Windows-Shift-2.

The location used for the weather status is hardcoded in ~/.xmobar/xmobarrc. It's decided by the first arg to "Run Weather" - in my case I've used LKTB, which is the ICAO code for Brno airport. Find your nearest airport's ICAO code using this page and find/replace both instances of LKTB (there should be two) in the file.

Now that the irritating part of XMonad is out of the way, you can see what else you can do by checking out the XMonad tour or take a look at the cheat-sheet below and experimenting. 

I'd also recommend fiddling around with ~/.xmonad/xmobarrc (documentation is here) adding new items to the status bar. Particularly the "Run Com ..." which let's you run arbitrary commands and will display whatever the output was . The reason it might look a little odd is that it's written in Haskell, so you might want to spent a little time with the excellent Learn You A Haskell to get familiar - but honestly you could get pretty far just copy-pasting existing lines and tinkering with them.

RPi - exposing http and ssh to the internet

This is just a quick guide for my friend Gonza to describe how SSH tunnelling can let you connect to a Raspberry Pi (or any other box running a unix-like OS) from anywhere even if it's behind an internet connection with a dynamic IP. This lets you avoid bothering to set up dyndns or similar. What you need is:

  1. RPi on home network (we'll call this rpi)
  2. remote box running linux, with a known IP address (we'll call this remote)

What we're going to do is establish an SSH connection between rpi and remote that will remain up at all times, and which will re-establish the connection without any user intervention. We'll be authenticating using an SSH key, so if you don't already have one run the following, I think the defaults are ok:

    me@rpi~ $ ssh-keygen -t rsa

And upload it to your remote server, and test it works nicely:

    me@rpi~ $ ssh-copy-id me@remote-server.com
    me@rpi~ $ ssh remote-server.com
    me@remote~ $ 

Next we'll make sure the remote has sshd configured so that as a client connecting via SSH you can specify the ports involved - so open up /etc/ssh/sshd_conf in your favourite editor:

    me@remote~ $ sudo emacs -nw /etc/ssh/sshd_conf
And either uncomment or add the following line:
    GatewayPorts clientspecified
Now that we've got rpi able to connect to remote via SSH we'll setup SSH tunnelling between the two. What this means is that we'll nominate some ports on remote which will have any traffic forwarded directly to some given ports on rpi - in this case I'm using:

type rpi port remote port 
ssh 40022 22
http 40080 8080

This will mean that not only can I SSH to rpi, but there's another one I can use for running, say, some web site or service. To do this we'll use autossh which is responsible for establishing the connection and keeping it up:

    me@rpi~ $ sudo apt-get install autossh
    me@rpi~ $ sudo autossh -Nf -M 40980 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i /home/me/.ssh/id_rsa -R remote-server.com:40080:localhost:8080 me@remote-server.com
    me@rpi~ $ sudo autossh -Nf -M 40922 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i /home/me/.ssh/id_rsa -R remote-server.com:40022:localhost:22 me@remote-server.com

To test this out, we can run a simple server on our rpi using nc:

    me@rpi~ $ while true; do { echo -e "HTTP/1.1 200 OK\r\n"; date ; uname -a ; echo; echo; } | nc -l 8080; done

And we can cURL the IP address of remote, which will forward the request/response between your laptop and rpi - I've used xxx.yyy.zzz.www in place of the actual IP address:

    me@laptop~ $ curl xxx.yyy.zzz.www:40080
    Sun May  1 13:36:14 UTC 2016
    Linux rpi 3.2.0-4-amd64 #1 SMP Debian 3.2.41-2+deb7u2 x86_64 GNU/Linux
We can try out connecting via SSH:
    me@laptop~ $ ssh me@xxx.yyy.zzz.www -p 40020
    me@rpi~ $ 

To get this command to run after we reboot we can muck around with systemd, or we could create a cron job - the latter is easier, so let's do that:

    $ crontab -e
And enter
    @reboot autossh -Nf -M 40980 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i /home/me/.ssh/id_rsa -R remote-server.com:40080:localhost:8080 me@remote-server.com
    @reboot autossh -Nf -M 40922 -o "PubkeyAuthentication=yes" -o "PasswordAuthentication=no" -i /home/me/.ssh/id_rsa -R remote-server.com:40022:localhost:22 me@remote-server.com

And if you want things to be a little easier you could add the following to your ~/.ssh/config:

    Host rpi
        HostName xxx.yyy.zzz.www
        Port 40020
This lets you connect to ssh without having to remember the IP address and port, so you can connect like so:
    me@laptop ~$ ssh me@rpi
    me@rpi ~$

Update, 2016-09-08: There's actually an even simpler way to do this if you don't have a remote machine and a domain, you can expose a tor hidden service. The caveat is that you're only able to access it from within the tor network, which means you won't be able to access it from your iPhone.

BeagleBone Black - iPhone as keyboard/mouse

Note: I wrote this a while ago specifically for my BeagleBone Black so some of the instructions refer to "opkg" - the package manager used by Ångström Linux. It looks like they've moved on to use Debian instead of Angstrom nowadays, but realistically you can adapt this guide and use the software on any linux distro on any device.

I thought it would be an interesting exercise to use my iPhone as an input device instead of a physical mouse and keyboard. It turns out it's pretty simple, thanks to Tuomas Räsänen's cool python-uinput module together with pybonjour for simple device discovery via Bonjour.

The "server" running on the Beagle and the iOS "client" (bad metaphors, sorry) can be retrieved via git:

$ git clone https://github.com/smcl/iBeagle
$ cd iBeagle

Preparing your Beaglebone Black

First copy the file iBeagle.py file to your beagle.

$ cd iBeagleServer
$ scp iBeagle.py beaglebone.local: # or whatever the username/IP is

Next there's a little bit of setup on the BeagleBone Black is required, as a kernel module and a couple of libraries are required

$ ssh beaglebone.local

Load the "uinput" module. this requires libudev

$ sudo modprobe uinput

The python module for uinput we're using requires udev-systemd, so install via opkg

$ sudo opkg install udev-systemd
$ git clone https://github.com/tuomasjjrasanen/python-uinput.git
$ cd python-uinput && sudo python setup.py install

Ensure avahi-daemon process is up and running

$ ps ax | grep avahi | grep running

Finally setup pybonjour - bonjour library I used for this. If you're having trouble relating to libdns_sd.so see the section "Appendix - udev trouble" at the end.

$ pushd /usr/src
$ wget https://pybonjour.googlecode.com/files/pybonjour-1.1.1.tar.gz
$ pushd pybonjour-1.1.1
$ tar -xzf  pybonjour-1.1.1.tar.gz
$ cd pybonjour-1.1.1
$ python setup.py install

Finally return to your iBeagleServer directory and run the client

$ popd && popd
$ python iBeagle.py

Preparing the iPhone Client

Currently you need to load the application using Xcode, so you'll need an iOS dev account and an iOS device authorised to your account. Open up iBeagleClient/iBeagleClient.xcodeproj, and build + run on your hardware.

When the server is running you should see your BeagleBone Black listed on the table when you launch the app. If not then try restarting the server, or waiting a few seconds.

Appendix - libudev trouble

I actually had a bit of trouble with this step initially. libdns_sd.so was missing, so I retrieved the avahi sources and built my own copy. The libdns_sd.so library was missing on my version of Angstrom Linux, so I built and installed it separately (which is slightly hacky, there's probably a more sensible way to achieve this)

$ wget http://avahi.org/download/avahi-0.6.31.tar.gz
$ tar -xzf avahi-0.6.31.tar.gz && cd avahi-0.6.31

We need to grab some pre-requisites + set PTHREAD_CFLAGS

$ export PTHREAD_CFLAGS='-lpthread'
$ sudo opkg install libssp-dev
$ sudo opkg install libintltool

And run configure so we only build as little as possible to just get the library we want

$ ./configure --disable-static --disable-mono --disable-monodoc --disable-gtk3 --disable-gtk --disable-qt3 --disable-python --disable-qt4 --disable-core-docs --enable-compat-libdns_sd --disable-tests --with-distro=none
$ make

Then (without running make install) we copy libdns_sd.so and libdns_sd.h into /usr/lib and /usr/include respectively

$ cp ./avahi-compat-libdns_sd/.libs/libdns_sd.so /usr/lib
$ cp ./avahi-compat-libdns_sd/dns_sd.h /usr/include

In my case it was trying to use libdns_sd.so.1 - so I also created a symlink to libdns_sd.so.1.

Thinkpad X250 - Debian, XFCE and X.org config

My trusty 2011 Macbook Air started to die recently, and since I'm getting more and more frustrated with OS X (neutering root in El Capitan, for example) I bit the bullet and picked up a Thinkpad X250 on a nice deal and switched to linux full-time. My distro of choice is Debian 8.3 ("Jessie") which is very nice under the hood,but the out-of-the-box UI is a little bit unpolished. Over the last week or so I spent some time bashing it into shape, and since it wasn't so simple I thought I'd share the main steps with anyone else out there.

Display/DPI and Fonts

The first thing is that the X250's screen is 1920x1080 but only 12.5 inches and when you first boot up the text appears to be scaled at 96dpi - and it's pretty tiny. Annoyingly the screen is not high-res enough for the standard HiDPI/Retina approach - scaling everything 2x - to work, everything looks a little too big. Getting something halfway is involves fiddling around with a lot of settings, and this is compounded by the fact that various apps and desktops have different ways of handling it. 

Note that this is mostly for XFCE - some of the other environments look and behave semi-OK (for example Cinnamon is reasonably usable but it eats my battery for breakfast) but I prefer the look and feel of XFCE even if I have to jump through a couple of hoops to get it to play nice.

First thing's first - my display's DPI setting was being incorrectly detected and I didn't have an xorg.conf to modify, so needed to generate one. Logout, switch to a terminal prompt, kill the lightdm process and use Xorg to generate the file:

    $ sudo service lightdm stop
    $ sudo Xorg --configure
    $ sudo cp /root/xorg.conf.new /etc/X11/xorg.conf # or from wherever Xorg created it

Then open up /etc/X11/xorg.conf and edit the Monitor section's DisplaySize - the ThinkPad X250's size in millimetres, so since the X250's screen is 276mm x 155mm we can set it to the following:

    Section "Monitor"
        Identifier "Monitor0"
        VendorName "Monitor Vendor"
        ModelName "Monitor Model"
        DisplaySize 276 155
        Option "DPMS"
    EndSection

After you reboot X11 will have loaded with the correct DPI setting. Things will still look a little wonky - but we're on the right track so sit tight and keep going.

Fixing the XFCE UI element fonts is pretty simple, go to Settings -> Appearance, select the Fonts tab, check the "Custom DPI Setting" box and input 150. 

If you have Chrome or Chromium installed you'll notice that the UI elements and fonts are pretty huge - this is because it's detected that you have a high DPI and has defaulted to scaling things by 2x. You'll need to edit the launcher so that it uses the --force-device-scale-factor to use 1.3 (a number I reached by pure trial-and-error):

Change the following line in /usr/share/applications/google-chrome.desktop:
    Exec=/usr/bin/google-chrome-stable  %U

to 

    Exec=/usr/bin/google-chrome-stable  --force-device-scale-factor=1.3 %U

If you use Chromium you can make a similar change to /usr/share/applications/chromium.desktop. So now Chrome will look a little saner - I also copied over the Times and Helvetica Neue fonts from my Mac and downloaded  Source Code Pro to make things look even better.

Next the login window - we fixed XFCE's DPI but the login window is still using 177, to alter it we need to fix up /etc/lightdm/lightdm-gtk-greeter.conf:

    font-name=Helvetica Neue 8
    xft-antialias=true
    xft-dpi=150
    xft-hintstyle=hintslight
    xft-rgba=rgb
After all this here's what Chrome running with the updated fonts looks like:

Qt fonts

Qt uses some slightly different settings - you need to ensure that ~/.fonts.conf is as appears below:

$ cat ~/.fonts.conf
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
    <match target="font" >
        <edit mode="assign" name="hinting" >
            <bool>true</bool>
        </edit>
    </match>
    <match target="font" >
      <edit mode="assign" name="hintstyle" >
	<const>hintslight</const>
      </edit>
    </match>
    <match target="font" >
        <edit mode="assign" name="antialias" >
            <bool>true</bool>
        </edit>
    </match>
</fontconfig>

To keep the layout consistent I opened up Settings -> Qt 4 Settings, went to the fonts tab and set it as follows:

Video Playback

I found that video playback was pretty choppy - to resolve it I had to just uncomment out a single option in xorg.conf:

    Section "Device"
        # ... lots of commented out options
        Option     "TearFree"           "true" # <-- uncomment or add this one
        Identifier  "Card0"
        Driver      "intel"
        BusID       "PCI:0:2:0"
    EndSection

Trackpad

Now that things look a little better we can fix the next couple of things that bothered me. By default there's a little area in the corner with counts as a "right" click that personally I don't use. Disabling it was as simple as commenting out the SoftButtonAreas and SecondarySoftButtonAreas in /etc/X11/xorg.conf.d/50-synaptics.conf

    Section "InputClass"
        Identifier "Default clickpad buttons"
        MatchDriver "synaptics"
        #Option "SoftButtonAreas" "50% 0 82% 0 0 0 0 0"
        #Option "SecondarySoftButtonAreas" "58% 0 0 15% 42% 58% 0 15%"
    EndSection

There's another couple of problems - the trackpad is extremely fast and sensitive by default, and additionally scrolling is too fast and has a sort of inertia that irritates me (I found I'd end up accidentally zooming in/out a lot). Scrolling can be tamed by adding the VertScrollDelta, CoastingSpeed and CoastingFriction sections to the same 50-synaptics.conf file as above, under the Driver "synaptics" section:

    Section "InputClass"
            Identifier "touchpad catchall"
            Driver "synaptics"
            MatchIsTouchpad "on"
    # This option is recommend on all Linux systems using evdev, but cannot be
    # enabled by default. See the following link for details:
    # http://who-t.blogspot.com/2010/11/how-to-ignore-configuration-errors.html
    #       MatchDevicePath "/dev/input/event*"
    	Option "VertScrollDelta" "200"
    	Option "CoastingSpeed" "1"
    	Option "CoastingFriction" "200"
    EndSection

For me adding the MaxSpeed option (which controls pointer sensitivity/speed) to 50-synaptics.conf didn't work, so I added the following to my ~/.xinitrc:

    synclient MaxSpeed=1.0 # it is 2.5 by default

The final touchpad tweak is to prevent it from registering touches as clicks while you're typing. XFCE has a setting that looks like it should work, but it leaves an agonising 2 second delay after you type before it enables the touchpad again. There's a handy utility to alter this which is syndaemon.

    syndaemon -i .2 -K -t -R -d

This can also go  into .xinitrc.

Power Management

By default the power management settings are a bit of a farce - my battery was exhausted after a handful of hours use even though it's pretty hefty. Strangely it seems that power management is still a bit of a ridiculous scene, I'd last operated a Linux laptop back in 2007 - a Thinkpad T40 - and sadly the out-of-the-box power management is pretty dire. There's a handful of useful applications which can help with individually tweaking things - like powertop - but thankfully there's a useful utility called tlp which appears to improve things significantly with only a little config required.

First you need to add the correct depot to your /etc/apt/sources.list - so add the following line to the end

    deb http://repo.linrunner.de/debian DIST main

And install the tlp and thinkpad packages:

    $ sudo apt-key adv --keyserver pool.sks-keyservers.net --recv-keys CD4E8809
    $ sudo apt-get update
    $ sudo apt-get install tlp tlp-rdw acpi-call-dkms

I still find power management a little unreliable - when closing the lid the system doesn't always sleep/suspend, the battery charge is sometimes reported incorrectly (it was stuck at "52%" for a while, which I didn't notice before it died on me). In addition XScreenSaver appears to mess things up too - when I enabled its power management settings it would kill performance after resuming from sleep (with the xorg process consuming >100% of the cpu). Disabling this altogether was fine.

Sound

Sound through the built-in speakers worked out of the box for me. However I have a little Bose Soundlink II bluetooth speaker which I like to use that's a little bit tricky. After pairing in blueman (which weirdly was a little bit trial-and-error) I wasn't sure how to get sound to play out of it. The solution was to install PulseAudio Volume Control, a utility that provides a nice graphical interface to controlling PulseAudio:

    $ sudo apt-get install pavucontrol

Then start the process that's playing the sound - so for me it's Chrome as I was watching Netflix. Open up pavucontrol, switch to the Playback tab find your application and select the bluetooth speaker from the dropdown. 

This being manual is a little bit frustrating but it's actually a minor step-up from OS X - where sometimes some apps wouldn't output sound to the speaker.

Conclusion

After the above tweaks my experience on Debian as a user is roughly on par with OS X (as a developer, it's far better of course). However there are still a number of things I am missing which would make my life a lot better.

  • Expose style window switcher. I know that there's skippy-xd but it is pretty buggy. There's an xfce bounty for this, so if anyone fancies picking up a whopping $70 then go nuts: https://www.bountysource.com/issues/3327306-expose-like-task-switcher-for-xfce
  • Trackpad gestures. I was quite fond of multi-touch gestures in OS X to switch workspaces, I haven't got this working in Linux/X.org just yet and I'm not sure if it's available.
  • AirDrop-style file sharing from iPhone

Hopefully I can pick away at those.



Debugging a TP-Link WR741ND using serial

I bought a little GL.iNet router and flashed it with a fresh OpenWRT image but I've been unable to do anything with it yet since it was unable to connect to the net via my apartment's ethernet connection. After some diagnostics I managed to find out that I needed to find the PPPoE username/password my working router used to connect, which was where my weird adventure began. 

My landlord or previous tenant had (smartly) changed the default password - admin/admin - so I wasn't able to use the web interface or SSH. I realised there was likely some Serial headers on the board I could use, so I dug out the schematics, cracked open my router and hoped to god that there was no login required, so that I could retrieve the settings from /etc/chap-secrets where I think they reside.

My router is a TP-Link WR741ND v4, a router that sadly doesn't already have serial pins which meant I needed to do a little soldering.


Two things need soldering, first is the connection between TX header and the onboard MIPS cpu as it's left open on this version of the router: 


Once this was done I just needed to connect some cables to the TX, RX and GND headers (I also connected up VCC in case I ever needed it in future):

Once these were sorted I was able to hook up my USB-TTL cable, open up terminal and crosss my fingers to see a very reassuring Linux boot in progress...

... followed swiftly by a login prompt!

I genuinely hoped that serial access would not be password protected, but it seems that I need to regroup and figure out how I can maybe retrieve the pppoe information some other way.

There is hope - typing "tpl" and hitting <Enter> during the boot process takes me to the u-boot prompt below 


So it's possible that either:

  1. I could coax uboot to boot into linux in single user mode
  2. Theres a way I could dump the data in the router's flash memory (I think md/mw/cp uboot commands can help here), find a way to access the filesystem this way. 
  3. I could get uboot to load a minimal linux image over TFTP (using tftpboot), then mount the flash file system and browse it.

 The final alternative is to brute force the username (probably still admin) and password, which is a little inelegant and slow.