RSS Atom Add a new post titled:
Debcon17 will be happening in Montreal

It's just been decided: Montreal will be hosting Debconf in 2017!

After trying our luck last year, the current Montreal bid team was chosen for organising the event. The competing bid for Prague was really strong, too, so the decision from the organising chairs was only made clear towards the end of the meeting.

Our team currently counts nine people, which is more than last year, and we hope to enroll more help as time advances towards the conference.

I'm thrilled of being able to bring such an interesting event to this city and look forward to working with everybody involved. I'm hoping this will be a great experience for myself and all of the others involved. At least for myself, it's one way of giving back to the community around the distribution I use on my personal computers and in my everyday job.

If you feel like giving a hand with organization, you can come and say hi in the local debian users group mailing list, or join our IRC channel: #debian-quebec on the OFTC network.

Using password-store with an alternate directory

pass (or password-store) is a neat program that helps you manage passwords in files encrypted with gpg.

The comand as it is already offers a lot: you can encrypt different directories to different sets of keys to have finer-grain control over sharing passwords; you can also use git to fetch and push password changes between people.

However, it's built without the idea of having multiple password repositories. It is possible to do so, but you have to know a little trick to do it. This post describes the trick that is already well known and published out there, but adds to it the possibility to use bash-completion with that trick.

The trick

That's super simple and it's documented in the pass(1) man page. In order to use an alternative password store, you need to set an environment variable:

export PASSWORD_STORE_DIR=~/.password-store-alternate

Then the next calls to pass will interact with this alternat store.

Setting up an alias to make it easier to interact with multiple stores

Then you think: I don't want to always set and unset the environment variable!

Easily fixed: just creat an alias that sets the variable only for each call to pass:

alias altpass='PASSWORD_STORE_DIR=~/.password-store-alternate pass'

Using bash-completion with your alias

Ok here comes the new detail (what was above is common knowledge within the pass users community). That alias suffers from not being able to auto-complete sub-command names or password entry/directory names. You can enable it by adding the following contents to the ~/.bash_completion file (create it if it doesn't exist):

# Add alias for alternate password-store
. /usr/share/bash-completion/completions/pass
_altpass() {
  # trailing / is required for the password-store dir.
  PASSWORD_STORE_DIR=~/.password-store-alternate/ _pass
}

complete -o filenames -o nospace -F _altpass altpass

There you have it. Now start a new terminal, and try using tab to auto-complete. The original pass command will still be auto-completing for the default password store.

SSH key rotation with monkeysphere

It's said to be a good practice to sometimes ro-ro-rotate your keys. It shortens the time span duging which your communications might be snooped upon if your key was compromised without your knowledge.

It's especially interesting to do it whenever there's a security issue like the one that was disclosed last week, cve-2016-0777 and cve-2016-0778, for which keys might have been exposed for 5 years to bein extracted by a malicious server.

I use monkeysphere to link my pubkey material to PGP the web of trust. This makes it super easy to make the pubkey available, and to have servers verify that the key it's getting was actually validated by some peers.

Here's how I rotated my key pair with monkeysphere.

Generate new subkey

First things first. Since we want to rotate keys, we need a new key. Monkeysphere does this for us and makes it super easy.

Before actually doing, though, let's take a look at my key before the process starts for comparative measures afterwards).

pub   4096R/0xC28592496BABC122 2014-06-11 [expires: 2016-06-10]
      Key fingerprint = C1CC 7A4B 7FBE 8ED3 7C00  F8B5 C285 9249 6BAB C122
uid                 [ultimate] Gabriel Filion <gabster@lelutin.ca>
uid                 [ultimate] Gabriel Filion <gabriel@koumbit.org>
sub   4096R/0x59BC891D96B9EF51 2014-06-11 [expires: 2016-06-10]
sub   4096R/0xC613C0506BBF1403 2014-09-18

You can see that I already have a subkey on the last line. That's the one I want to replace. So let's create the new key:

monkeysphere gen-subkey -l 4096

After this operation is complete, you should be able to notice a new subkey on your PGP key:

pub   4096R/0xC28592496BABC122 2014-06-11 [expires: 2016-06-10]
      Key fingerprint = C1CC 7A4B 7FBE 8ED3 7C00  F8B5 C285 9249 6BAB C122
uid                 [ultimate] Gabriel Filion <gabster@lelutin.ca>
uid                 [ultimate] Gabriel Filion <gabriel@koumbit.org>
sub   4096R/0x59BC891D96B9EF51 2014-06-11 [expires: 2016-06-10]
sub   4096R/0xC613C0506BBF1403 2014-09-18
sub   4096R/0x595B733A8B95E6F1 2016-01-23

Export new subkey to ssh-agent alongside old one

This part should be super simple if you have only one secret key in your keyring. Just launch the command at the end of this section and you're done. However, in my case I have a key that's revoked and monkeysphere tries to export material from this key. In order to prevent this, I use the environment variable MONKEYSPHERE_SUBKEYS_FOR_AGENT that I set in my ~/.bashrc file.

Let's get each subkey's fingerprint. Some users might need to use this super intuitive gpg call. For some others, only one argument is needed; I haven't yet determined what influences this, but in all cases using the argument twice will work for everyone.

$ gpg --fingerprint --fingerprint gabster@lelutin.ca
[...]
pub   4096R/0xC28592496BABC122 2014-06-11 [expires: 2016-06-10]
      Key fingerprint = C1CC 7A4B 7FBE 8ED3 7C00  F8B5 C285 9249 6BAB C122
uid                 [ultimate] Gabriel Filion <gabster@lelutin.ca>
uid                 [ultimate] Gabriel Filion <gabriel@koumbit.org>
sub   4096R/0x59BC891D96B9EF51 2014-06-11 [expires: 2016-06-10]
      Key fingerprint = CB3D 48CE 55CD 1FAB B1E4  D0C3 59BC 891D 96B9 EF51
sub   4096R/0xC613C0506BBF1403 2014-09-18
      Key fingerprint = 39C9 47C6 48F4 664C FFBB  C83A C613 C050 6BBF 1403
sub   4096R/0x595B733A8B95E6F1 2016-01-23
      Key fingerprint = D480 05C9 0B18 ABF7 965C  7E01 595B 733A 8B95 E6F1

Now that we have this information, we can adjust the environment variable. Monkeysphere's man page says that the variable takes a space-separated list of fingerprints so I removed all spaced from the output above:

export MONKEYSPHERE_SUBKEYS_FOR_AGENT="D48005C90B18ABF7965C7E01595B733A8B95E6F1 39C947C648F4664CFFBBC83AC613C0506BBF1403"

Finally, we can export the new subkey to the ssh agent:

monkeysphere s

After this, you should be seeing in the output of ssh-add -L the same thing as in monkeysphere u 'gabster@lelutin.ca'

Revoke old subkey

Now we can revoke the old subkey. Doing so will not stop monkeysphere from exporting it to ssh-agent. It simply creates a public revocation object on the subkey's public part.

gpg --edit uid
> key 2
> revkey
> save

(optional) publish updated PGP key to key servers

If you are using the public key servers for publishing your public key material, now is a good time to send your updated key.

gpg --send-keys gabster@lelutin.ca

Revoked subkeys that are published to key servers won't get imported by monkeysphere-authentication update-users anymore; they will actually get removed from computers (after all that's the point of monkeysphere, to import only public keys that are valid). So once this runs on computers to which you should have access, only you new subkey should be present on computers.

Of course, for this to actually happen you will have to wait for propagation to happen between the key servers.

For people that use other means of publishing keys, you'll have to send your updated public key to the right communication channel for your key to end up getting updated by monkeysphere.

Install new key everywhere

If you're only using your subkey for monkeysphere-enabled computers, then you're all done! But if you're installing this same public key on computers that are not using monkeysphere (e.g. the traditional authorized_keys way), you'll have to install your new key everywhere and remove the old one.

You can get your new public key in a format that's usable with authorized_keys with:

monkeysphere u 'gabster@lelutin.ca'

Clear out old subkey

Once you're certain that the old key is not installed anywhere anymore, you can stop exporting it to your ssh-agent. For this, we'll change the environment variable again and remove the old subkey's fingerprint.

export MONKEYSPHERE_SUBKEYS_FOR_AGENT="D48005C90B18ABF7965C7E01595B733A8B95E6F1"

You can then clean out the old key from your running agent. First manually export the new value of the variable you just set in your ~/.bashrc. Then remove keys from your agent (for this part you might want to be more careful and use -d to export single keys if you have other identities present in your ssh-agent) and if you blasted everything out like I did, re-export key material from monkeysphere:

ssh-add -D
monkeysphere s

Rotation completed!

How should I order things in ssh config

This may seem super obvious for some people, but I've actually just discovered this for myself and I think documentation doesn't make this super easy to know. This discovery solved some of my woes with configuring my ssh client.

Here's a motto that you should keep in mind when modifying your ssh_config file:

In ssh_config, specific comes first and generic last.

OpenSSH tends to parse the ssh_config file from top to bottom, and by doing so, as soon as you set an option other blocks that might match for the same host further down won't be able to set that same option again. In that sense, having wildcard blocks at the end of the file (or at least after all other hosts that it can match) makes sense since such a block will set the option for all matching hosts only if it hasn't already been set above.

Debian jessie live image

A quick note to ppl who want to use the Debian live jessie image (standard, no X environment):

The auto login was busted up since wheezy and you now need to manually login for that image to be useful. The credentials are:

  • User: user
  • Password: live

With this login, you can then sudo to perform any task you want.

Bash random stuff

With bash, there are lots of things that you can do. Some of them make GUIs look like interfaces for kids. Some others are not super useful, but intellectually fun.

Here's a random dump of things I've kept around as notes.

Who's using that?

To know if files or directories are being used by programs, two commands are super useful: fuser and lsof.

fuser

To know the PIDs of programs that have a certain file in their file descriptors, and the user names under which they are running:

fuser -u /var/log/mail.log

To show PIDs using any file under a mounted filesystem:

fuser -m /srv/

Create a screen session on a serial device, but only if nothing is already using it. Otherwise, try reconnecting to the current screen session:

if fuser -s /dev/ttyUSB2; then screen -x; else screen /dev/ttyUSB2 115200; fi

lsof

To list all files that are open by a certain process ID:

lsof -p 4194

To get all files open by a certain user:

lsof -u joejane

To see all established IPv4 connections from a certain process ID:

lsof -i 4 -a -p 31936

List all processes that have established an SSH connection:

lsof -i :22

Getting rid of all spaces in a tree of files

# this trick depends on bash features
# this command doesn't take any argument. it'll work on the current working
# directory and all of its subdirectories
nomorespace () { ls -1| while read i; do j=${i// /_}; if [ "$i" != "$j" ]; then mv "$i" "$j";fi; done; for i in $(find . -maxdepth 1 -type d -not -name "."); do pushd $i; nomorespace; popd; done; }

Switching file encoding

Sometimes it's useful to switch files that you get from the internet from one encoding to another that's more useful for you.

Transform flac files into ogg files

# This expects files to have track number at the start of the file followed by
# a dash like this:
# 01-Track_title.flac
for i in *.flac; do track=$(echo $i|sed -e 's/\([0-9][0-9]\).*/\1/'); title=$(basename $i .flac|sed -e 's/^[0-9]\+-//' -e 's/_/ /g'); flac -sdc $i | oggenc -a "Ali Farka Touré" -l "The river" -N "$track" -t "$title" -o $(basename $i .flac).ogg -; done

Transform m4a files into ogg files

# Same expectations for the filename as above
for i in *.m4a; do track=$(echo $i |sed -e 's/\([0-9][0-9]\).*/\1/'); title=$(basename $i .m4a|sed -e 's/^[0-9]\+-//' -e 's/_/ /g'); mplayer -quiet -vo null -vc dummy -ao pcm:waveheader:file="rawaudio.wav" "$i"; oggenc -a "Aphex twin" -l "Drukqs" -N "$track" -t "$title" -o ${track}-$(echo $title | sed -e 's/ /_/g').ogg rawaudio.wav; rm -f rawaudio.wav; done

Redefining builtin commands

This is rather more fun than useful, but I found it on a site that was instructing about what you can do when the infamous "rm -rf /" was run on a server and you need to salvage what you can from the remains of the explosion.

ls() {
  [ "x$1" == "-a" ] && ALL=".*"
  for i in $ALL *; echo $i; done
}
cat() {
  while read line; do echo $l; done < $1
}
Bash uglyness of the day

Here the Bash uotd:

Say you've got a list of items separated by new lines, and you'd like to concatenate them in a string, but by ensuring you enclose each item in single quotes so as to enclose spaces and weird characters safely.

You do the following:

resulting_string=
for i in $list_of_things; do
   resulting_string="${resulting_string}'${i}' "
done
# All good here, look at the contents.
# should be giving you what you expect
echo "$resulting_string"

Now try supplying that to a command:

some_command $resulting_string
# OOPS, some_command has an argv that would look like this (notice how it
# actually receives the single quotes with the arguments):
argv[0]=some_command
argv[1]='blah'
argv[2]='blih'

How do you fix that? Obvious, isn't it: you either eval or enclose the whole thing in another shell!

sh -c "some_command $resulting_string"

I really don't like shell scripting...

New OpenPGP key

For those of you who have already signed my key, and for those who might have considered it, I am migrating to a new key.

The reason is that I would like to move to a 4096bit RSA key to hopefully get a longer time before the three- or four-letter (here in Canada) organisations can bruteforce my encrypted communications.

My new key can be found on key servers and has the following fingerprint:

C1CC 7A4B 7FBE 8ED3 7C00 F8B5 C285 9249 6BAB C122

You might also notice that I removed one uid from the new key. Since my trust for the Google is eroding now to what looks like a ball of regurgitated cat fur, I'd like to encourage people to not use my gmail address anymore.

I've prepared a key transition statement so that those who've already signed my old key can verify that this is not a fake post from my alter-ego. See the following link:

key-transition-2014-07-15.txt

SquirrelMail and encrypted headers

Well well.. today I had to sort out a spam run that was originating from our webmail and boy was I happy to have some way to link email to some account.

But .... eeeek I saw something I didn't want to be real :(

Let's talk about the way SquirrelMail "encrypts" the headers it adds to mail for tracking purposes.

Purpose of those headers

The two headers that SquirrelMail adds are one for the user name from which the mail was sent (e.g. authenticated user name) and the other is some kind of hash on the from field for which I don't quite care for the purposes of killing spammers.

Format of those headers

When you look at an email that was sent by SquirrelMail (and for which you set the variable $encode_header_key -- which should be done automatically on debian -- you can see something that will look like the following:

X-Squirrel-UserHash: KVcBIR8rLwwFNDxaLkpWew==
X-Squirrel-FromHash: fQAIWRtqdgJ/

How are they generated?

How the heck is that scheiße generated?

OK let's dig into the code that generates the headers. In file /usr/share/squirrelmail/class/deliver/Deliver.class.php, inside function prepareRFC822_Header() we can find the following two lines of interest (with 3rd line before just to give more context):

        $rn = "\r\n";
[...]
            $header[] = 'X-Squirrel-UserHash: '.OneTimePadEncrypt($username,base64_encode($encode_header_key)).$rn;
            $header[] = 'X-Squirrel-FromHash: '.OneTimePadEncrypt($this->ip2hex($REMOTE_ADDR),base64_encode($encode_header_key)).$rn;

... wait what did we just see?

... yep, the code from file /usr/share/squirrelmail/functions/strings.php does confirm it. It is a one time pad.

So the headers are encrypted with a one time pad with a never-changing-key. Is it just me or is that the textbook example of how to NOT use a one time pad?

I will leave reproducing this as an exercise to the reader, but I will claim that if you're able to catch a few dozen email with such headers, you will be able to easily retrieve part of the key -- enough to be able to decrypt most headers that you intercept.

How do I decrypt those headers?

Simple, I've written a small script for that that actually uses the function from SquirrelMail's code. Shame we can't just include the file that defines the functions though, so I just copied the function definition in the script. It's tailored for Debian since the $encode_header_key variable is defined in /etc/squirrelmail/config_local.php but you can easily change this to get the key from wherever it's lying on your disk:

#!/usr/bin/php
<?php

/**
 * Decrypts a password from the cookie
 *
 * Decrypts a password from the cookie, encrypted by OneTimePadEncrypt.
 * This uses the encryption key that is stored in the session.
 *
 * @param string string the string to decrypt
 * @param string epad the encryption key from the session
 * @return string the decrypted password
 */
function OneTimePadDecrypt ($string, $epad) {
    $pad = base64_decode($epad);

    if (strlen($pad)>0) {
        // make sure that pad is longer than string
        while (strlen($string)>strlen($pad)) {
            $pad.=$pad;
        }
    } else {
        // FIXME: what should we do when $epad is not base64 encoded or empty.
    }

    $encrypted = base64_decode ($string);
    $decrypted = '';
    for ($i = 0; $i < strlen ($encrypted); $i++) {
        $decrypted .= chr (ord($encrypted[$i]) ^ ord($pad[$i]));
    }

    return $decrypted;
}

set_include_path('/etc');

include "/etc/squirrelmail/config_local.php";

while (! feof(STDIN)) {
  $val = fgets(STDIN);

  $res = OneTimePadDecrypt($val, base64_encode($encode_header_key));

  print ($res);
}

To use the script, just invoke it as a script within your shell of choice and for each line of text that you give to it on stdin, it will return the decrypted value to stdout until it hits EOF.

So ... what's all this fuss about?

If leaking your usernames is bad for you, DON'T USE THE SQUIRRELMAIL ENCRYPTED HEADERS. To disable them, you can just set the $encode_header_key variable to an empty string.

The downside to not using the headers is that you can't easily track down trouble makers. But you can always enable the headers when you need to track such an annoyance.

Nagging about PGP key expiry

At the org I work with, we've published a PGP key a bunch of years ago for our support email that creates tickets in our RT instance. RT is nice and does support GPG encrypted emails.

As it happens, we've been dropping the ball some times with regards to keeping that key up to date (e.g. refreshing expiry time). It happened a couple of times that the key expired and we didn't notice until someone told us about it.

That's not good enough! We published that key and it is still valid so we should make sure that ppl can trust it by refreshing expiry time when appropriate.

Here comes Nagios to the recuse ;)

I've cooked up a small Nagios plugin for checking a key's expiry date:

https://github.com/lelutin/nagios-plugins/blob/master/check_gpg

It comes off as CRITICAL when the key is already expired and can optionally come off as WARNING when the key will expire within a certain number of days. It also comes off as CRITICAL if the key was revoked (since that makes the whole expiry date useless to check).

Now we'll get a sweet notification from nagios 1 month in advance and will be able to keep that key up to date, and our users' confidence into that key intact.

See older posts

This blog is powered by ikiwiki.