Getting Window Properties when your Mouse is Unavailable

Or, floating the menu in xfce

I’m currently using XMonad in Xubuntu, which has been really lovely. However, I got very tired of the xfce4’s menu also being tiled. The XMonad.ManageHook package provides tools for dealing with your windows (floating, ignoring, whatever) provided you have some information about them, like the title.

-- signatures from XMonad.ManageHook

title :: Query String
-- Returns the window title.

doIgnore :: ManageHook
-- Map the window and remove it from the WindowSet.

We can get the window’s title by checking the value of _NET_WM_NAME(UTF8_STRING), which can be done through xprop. But using xprop to get the title of xfce4’s menu by clicking on the open menu doesn’t quite work out

$ xprop
xprop: error: Can't grab the mouse.

We need a way to get information about all the windows we have open. Enter xwininfo!

$ xwininfo -children -root
# lots of stuff here

Unfortunately at this point you have to manually scan the output for what you’re looking for, if you have no idea what it might be called.

At this point we can utilize xprop to get more info about our window, if we choose..

$ xprop -name "Whisker Menu"

…but in this instance there was no need. The following snippet added to your ManageHook, will ignore the xfce4 whisker menu.

title =? "Whisker Menu" --> doIgnore

XMonad + XFCE

After 5 years or so, I have switched from Arch Linux to Xubuntu. Whether or not this change is permanent remains to be seen. I do miss pacman quite a bit.

Currently running XMonad as my window manager. I’m using xmonad-log-applet to send info (xmonad layout, focused window title, etc) to xfce4-panel.

Here’s a relatively bare-bones xmonad.hs that makes XMonad in XFCE4 a little more comfortable. Actually the most important part here is replace; without it, I was running into all kinds of funky issues with xfce4-panel.

A Palindrome Encounter

On May 24, 2016 I looked at the time in the evening and it was 5:45. Ah, a palindrome! I thought. (Looking at it as a number/sequence of digits rather than a sequence of characters.) The next time I looked at the time it was 6:56. Also, you’ll notice, a palindrome.

A connection between these two palindromes: the absolute difference between the unique digits of both these palindromes is 1 (|5-4|=|6-5|). One just so happens to be the unique digit(s) making up the palindrome 11, which is also the sum of the unique digits of the latter palindrome (6+5). The sum of the unique digits of the first palindrome is 9 (5+4), which is also a palindrome, if trivial.

Ahhhh, life!

p.s. I remembered the date as being May 24 because, where I live, we write that date as 5/24 (month/day). Perhaps it would have been fitting to have this observation on 5/25, thereby bagging another palindrome. However, May 24th is one day away from May 25, which is even more fitting. (In that same sense, May 26th would have pleased me too.)

p.p.s. I suppose this breaks down a little if you live your life on a 24hr clock… which seems to be quite common.

the cat is not away

In a true test of my ability to navigate via keystrokes, my mouse has disappeared. (Not the physical one, but the pixelated one.)

It’s going great so far. Until, you know, I encounter a flash video…

Chrome/Chromium is sound-greedy

I was having an issue where chromium (and chrome) would… grab onto my sound device? Basically it would not play sound if another application (eg firefox) was. When chromium was able to play sound, then these other applications could not.

Installing the pulseaudio-alsa package on Archlinux fixed this. It did require a restart.

emacs: Indirect Buffers

Say you have buffers A and B both visiting the same file. Sure, you can view different parts of this file in A and B, but once you narrow in one buffer, the same section is narrowed in the other.

When this is not the behaviour you want (when would you actually want this behaviour, is the real question imho), use indirect buffers!

An indirect buffer shares the text of some other buffer, which is called the base buffer of the indirect buffer. In some ways it is a buffer analogue of a symbolic link between files.

[…]

The text of the indirect buffer is always identical to the text of its base buffer; changes made by editing either one are visible immediately in the other. But in all other respects, the indirect buffer and its base buffer are completely separate. They can have different names, different values of point, different narrowing, different markers, different major modes, and different local variables.

Handy-dandy key chord C-x 4 c (clone-indirect-buffer-other-window): analogous to C-x 4 f, this binding creates an indirect buffer of the current buffer in another window. (Remember that c by remembering clone.)

Adding tap0 on ArchLinux

MirageOS networking examples tend to use ifconfig for this. On ArchLinux, ifconfig is (allegedly) deprecated, and we tend to use ip for things.

# ip tuntap add tap0 mode tap
# ip addr add 10.0.0.2/255.255.255.0 dev tap0
$ ping 10.0.0.2 # browse to http://10.0.0.2 if applicable

Logging opam install Errors

$ echo y | opam install mirage >> iopage.err 2>&1
  • echo y because opam wants confirmation that you really want to install
  • 2>&1 redirects both stdout and stderr to iopage.err

Though what I’d really like is to be able to redirect stdout/err to a file and still have them output to the terminal.

EC2 – Bundling Images

The image bundling process (ec2-bundle-image from the Amazon EC2 AMI Tools) is the first step in creating an amazon machine image (AMI). This process creates an XML manifest and (one or more) image part(s). The image parts are created by compressing, encrypting and then dividing the original image.

For the record, there is an upper limit on the size of an image that can be turned into an AMI (10GB, I believe?)

This is a description of the bundling process as I understand it. Be warned that my understanding is wrong. :( While writing this post I have discovered why my bundled manifests were not working. Sort of.

In the following discussion the file input to the bundling process is mymirage.img.

Input Parameters

required

  • the image! (mymirage.img)
  • user’s private key
  • user’s certificate

optional

  • ec2 certificate

Encrypting the original image

ec2-bundle-image runs this command:

$ openssl sha1 < /tmp/ec2-bundle-image-digest-pipe-10174 & tar -c -h -S --owner 0 --group 0 -C /tmp mymirage.img | tee /tmp/ec2-bundle-image-digest-pipe-10174 | gzip -9 | openssl enc -e -aes-128-cbc -K aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -iv bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb > ec2_tmp/mymirage.img.tar.gz.enc

The image in tarred, gzipped and then encrypted (AES-CBC with a 128-bit key). The result is stored in mymirage.img.tar.gz.enc. A digest (sha1) of this file is calculated simultaneously. Amazon will attempt to recreate this when launching the VM, terminating the instance if it cannot.

A note on the key & iv

The key and iv are generated using gensymkey

# Load and generate necessary keys.
key = Format::bin2hex( Crypto::gensymkey )
iv = Format::bin2hex( Crypto::gensymkey )

despite the fact that Amazon implements a geniv function. But why?

# Generate an initialization vector suitable use with symmetric cipher.
#
def Crypto.geniv
OpenSSL::Cipher::Cipher.new(SYM_ALG).random_iv
end

#----------------------------------------------------------------------------#

##
# Generate a key suitable for use with a symmetric cipher.
#
def Crypto.gensymkey
OpenSSL::Cipher::Cipher.new(SYM_ALG).random_key
end

The key and iv both are encrypted twice, once with the user’s X.509 certificate and once with amazon’s (the optional ec2 certificate mentioned earlier). These encryptions are included in the manifest.

Dividing the image into parts

The encryption result mymirage.img.tar.gz.enc is divided into parts of 10MB, resulting in the files

$ ls
mymirage.img.part.0
mymirage.img.part.1
# etc

I have yet to implement this. My test mirage images are about 5MB so I’ve just been copying the contents of mymirage.img.tar.gz.enc to a file called mymirage.img.part.0. Which works.

Actually I have tried to implement this. But it is only writing 65536 bytes per part instead of the desired 10MB.

(* split a file into parts of 10MB or less return a list of the names of the files created *)
let split file =
let open Unix in
let chunk_size = 1024 * 1024 * 10 in
let buffer = String.create chunk_size in
let fd_in = openfile file [O_RDONLY] 0 in
let rec copy_loop n ps () =
let part =
let name = Filename.(chop_extension @@ chop_extension @@ name_only file) in
tmp @@ Printf.sprintf "%s.img.part.%i" name n in
let ch_out = openfile part [O_WRONLY; O_CREAT; O_TRUNC] 0o666 in
match read fd_in buffer (n * chunk_size) buffer_size with
| 0 -> close fd_in; ps
| r -> print_endline @@ Printf.sprintf "writing %i bytes" r;
ignore (write ch_out buffer (n * chunk_size) r);
close ch_out;
copy_loop (succ n) (part::ps) () in
copy_loop 0 [] ()

Components of the XML manifest

The xml manifest has this structure:

  • `manifest`
    • `version` a string that identifies the type of manifest
    • `bundler` (optional?) information about who created the manifest
      • `name`
      • `version`
      • `release`
    • `machine_configuration`
      • `architecture` `x86_64` for our purposes
      • `kernel` (optional) a string eg `aki-fc8f11cc`
    • `image`
      • `name` string eg `mymirage.img`
      • `user` 12-digit AWS user id
      • `type` the string “machine” for our purposes
      • `digest` SHA1 digest of the encrypted image (created during the compression & encryption process mentioned above)
      • `size` size of the original image (eg size of `mymirage.img`)
      • `bundled_size` size of the compressed, encrypted image (eg size of `mymirage.img.tar.gz.enc`)
      • `ec2_encrypted_key` RSA public encryption of the key used to encrypt the compressed image. The public key is from the ec2 certificate
      • `user_encrypted_key` RSA public encryption of the key used to encrypt the compressed image. The public key is from the user’s certificate
      • `ec2_encrypted_iv` RSA public encryption of the iv used to encrypt the compressed image. The public key is from the ec2 certificate
      • `user_encrypted_iv` RSA public encryption of the iv used to encrypt the compressed image. The public key is from the user’s certificate
      • `parts` info on the 10MB parts into which the encrypted image was split
        • `part` one or more of these
          • `filename` string eg `mymirage.img.part.0`
          • `digest` SHA1 digest from the contents of the part
    • `signature` SHA1 digest of the XML “ and “ info signed with the user’s private key

A number of these fields are easy to fill (eg size or version). Unfortunately a number of them (eg ec2_encrypted_key) are not easily replicated, making it difficult to pinpoint exactly what is wrong with the manifests I’ve created.

Verifying manifest correctness

ec2-unbundle promises to extract an image given a manifest and private key. Sadly….

$ ec2-unbundle -m mymirage.img.manifest.xml -k onekeytorulethemall.pem --debug
ERROR: padding check failed
#
/usr/local/ec2/ec2-ami-tools-1.5.3/lib/ec2/amitools/unbundle.rb:49:in `private_decrypt'
/usr/local/ec2/ec2-ami-tools-1.5.3/lib/ec2/amitools/unbundle.rb:49:in `unbundle'
/usr/local/ec2/ec2-ami-tools-1.5.3/lib/ec2/amitools/unbundle.rb:100:in `main'
/usr/local/ec2/ec2-ami-tools-1.5.3/lib/ec2/amitools/tool_base.rb:201:in `run'
/usr/local/ec2/ec2-ami-tools-1.5.3/lib/ec2/amitools/unbundle.rb:109:in `'

…so I hardcoded my keys in…

# Extract key and IV from xml manifest
# key = pk.private_decrypt(Format::hex2bin( manifest.ec2_encrypted_key))
# iv = pk.private_decrypt(Format::hex2bin( manifest.user_encrypted_iv))
key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
iv = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"

… and discovered that my digest is incorrect!

$ ec2-unbundle -m mymirage.img.manifest.xml -k onekeytorulethemall.pem --debug
Pipeline.execute: command = [/bin/bash -c 'openssl sha1 /tmp/image-unbundle-pipeline-pipestatus-020140731-20445-zhcuih & echo ${PIPESTATUS[1]} > /tmp/image-unbundle-pipeline-pipestatus-120140731-20445-y3ajkk & echo ${PIPESTATUS[2]} > /tmp/image-unbundle-pipeline-pipestatus-220140731-20445-13o3moo & echo ${PIPESTATUS[3]} > /tmp/image-unbundle-pipeline-pipestatus-320140731-20445-5l5cs2 & echo ${PIPESTATUS[4]} > /tmp/image-unbundle-pipeline-pipestatus-420140731-20445-vxbp20']
Pipeline.execute: output = [(stdin)= e65de62e203671c803b532f046aa5479277790d6]
ERROR: invalid digest, expected da39a3ee5e6b4b0d3255bfef95601890afd80709 received e65de62e203671c803b532f046aa5479277790d6

Oddly enough re-creating the manifest /can/ produce the digest amazon calculates, but most times will not. I have no idea why this is, but at least I can identify when it is happening. I suspect the problem is more with the cmd being run than with the OCaml code.

(* calculate digest; compress & encrypt image *)
let pipeline ~digest_pipe ~tar ~key ~iv ~encrypted_destination =
let open Unix in
let cmd = Printf.sprintf "openssl sha1 %s"
digest_pipe tar digest_pipe key iv encrypted_destination in
let ic = open_process_in cmd in
let digest = input_line ic in
close_process_in ic;
digest

What remains to be done

Unfortunately I still haven't launched a proper, working instance:

Warning: unable to open an initial console.
Kernel panic - not syncing: No init found. Try passing init= option to kernel.

A diff (thank you internet) on the original image and ec2-unbundled image showed that I hadn’t, say, inadvertently corrupted something during the bundling process. So I’m about 99.997% certain that (but for the digest issue) the issue here is related to how I turned the xen kernel into an image.

EC2 Documentation (warning: pdf link!) says an initrd needs to be generated. I don’t see my script doing that. I have a feeling I’ve accidentally deleted that part (I am prone to these kinds of accidents…). Alas the original script on the mirage wiki is either broken or has mysteriously disappeared. (I’m actually not sure which it is. The first time I checked it out, the page was empty. The second time, literally nothing happened when I clicked the link..)

But anyway, what I have left to do

  • fix (or find) the image creating script
  • consistently calculate the correct digest

(and less pressingly)

  • split compressed/encrypted large images into 10MB pieces