Enable more locales in stock Debian installations

If you wonder why

 $ php -r "setlocale(LC_TIME, 'de_DE.UTF-8'); echo strftime ('%A %e %B %Y', mktime (0, 0, 0, 12, 22, 1978));"

gives you Freitag 22 Dezember 1978 on most systems like f.e. openSuSE and Ubuntu, but Friday 22 December 1978 on Debian, you need to remember that the Debian guys outsmart everything and everybody with a shell script and a configuration file, just to keep your installation lean and clean.

In this particular example, edit /etc/locale.gen and add de_DE.UTF-8 UTF-8 (or anything else listed in /usr/share/i18n/SUPPORTED), hit save and then execute

 $ sudo /usr/sbin/locale-gen

and voila, the above PHP call (and everything else which requests a German locale) works!

Read encrypted emails via webmail?

I was recently asked how to read encrypted emails securely in some untrusted environment via webmail. Imagine you’re sitting on someone else’ computer and absolutely need to check your inbox for this one encrypted email which contains a password without which you can’t continue. Or you’re in some internet cafe and got an important encrypted email – how would you do that?

Actually, the only thing which comes into my mind here is a combination of Portable Firefox and FireGPG on an USB stick (possibly encrypted). This, of course, bears a couple of problems:

  1. If you don’t know which OS your “target” computer has, you need to have this “tandem” in at least three different binary versions, Mac OS X, Linux and Windows. While this doesn’t sound too hard (three partitions on the same drive), it’ll probably harder to encrypt all three and have something like “plug-and-mail-ready” for the target OS.
  2. If you use a non-standard webmailer (i.e. no public service, but an own setup, like I have with roundCube Webmail), you won’t have a really good integration with FireGPG (i.e. no interface buttons, auto-decryption and other stuff) unless the webmail software plans support for FireGPG. (roundCube targeted it for “later“.)
  3. And maybe the greatest show-stopper is the question: Is it really secure in untrusted environments? After all, GnuPG needs to load your private key into RAM to decrypt your message, and if it resides unprotected there (does it?), it could be, at any time, be read out by some hidden daemon and boom, your private key would be compromised…

How would you solve this dilemma? A VPN to a trusted PC from which you send and receive emails?

If there are no other good solutions then I guess people will have to choose between accessibility from everywhere and email security. And I bet they don’t choose security…

Change svn:externals quickly

If you’ve worked with external repository definitions and branches before, you probably know the problem: If you create a new branch off an existing one or merge one branch into another, subversion is not smart enough to update svn:externals definitions which point to the same repository, but rather keep them pointing to the old (wrong) branch. (I read they fixed that with SVN 1.5 by supporting relative URLs, but still, a couple of people might not be able to upgrade and I want to keep rather explicit with external naming anyways.)

Anyways, today at work I was so sick of the problem that I decided should hack something together. Here is the result:

#!/bin/bash
export LANG=C
if [ $# -ne 2 ]
then
    echo "Usage:" $(basename $0) "<old> <new>"
    exit 1
fi

old=$1
new=$2
repo_root=`svn info | grep "Repository Root" | cut -f3 -d" "`;

if [ -n "$(svn info $repo_root/$new 2>&1 | grep "Not a valid URL")" ]
then
    echo "$repo_root/$new is not a valid URL"
    exit 1
fi

for ext in  $(svn st | grep -e "^X" | cut -c 8- | xargs -L1 dirname | uniq)
do
    externals=$(svn propget svn:externals $ext)
    if [[ "$externals" == *$repo_root/$old* ]]
    then
        externals=${externals//$repo_root\/$old/$repo_root\/$new}
        svn propset svn:externals "$externals" $ext
    fi
done

Save this into a file, make it executable and you’re good to go! The script is smart enough to check if the target URL (based on the repositories’s root and the given <new> path) actually exists and also only changes those external definitions which actually match the repository root.

Fun!

SSL Verification with Qt and a custom CA certificate

So I wanted to make my application updater for guitone SSL-aware the other day. The server setup was an easy job: Add the new domain (guitone.thomaskeller.biz) to cacert.org, create a new certificate request with the new SubjectAltName (and all the other, existing alternative names – a procedure where this script becomes handy), upload to CAcert, sign it there, download and install the new cert on my server, setup a SSL vhost for the domain – done!

Now, on Qt’s side of things using SSL is rather easy as well, the only thing you have to do is give the setHost method another parameter:

QHttp * con = new QHttp();
con->setHost("some.host.com", QHttp::ConnectionModeHttps);
con->get("/index.html");
// connect to QHttp's done() signal and read the response

This should actually work for all legit SSL setups if Qt (or, to be more precise, the underlying openssl setup) knows about the root certificate with which your server certificate has been signed. Unfortunately, CAcert’s root certificate is not installed in most cases, so you basically have two options:

  1. Connect to QHttp’s sslErrors(...) signal to the QHttp::ignoreSslErrors() slot. This, of course, pretty much defeats the whole purpose of an SSL connection, because the user is not warned on any SSL error, so also legit errors (certificate expired or malicious) are just ignored. (*)
  2. Make the root certificate of CAcert known to the local setup, so the verification process can proceed properly.

I decided to do the latter thing. This is how the code should now look like:

QHttp * con = new QHttp();
QFile certFile("path/to/root.crt");
Q_ASSERT(certFile.open(QIODevice::ReadOnly));
QSslCertificate cert(&certFile, QSsl::Pem);
// this replaces the internal QTcpSocket QHttp uses; unfortunately
// we cannot reuse that one because Qt does not provide an accessor
// for it
QSslSocket * sslSocket = new QSslSocket(this);
sslSocket->addCaCertificate(cert);
httpConnection->setSocket(sslSocket);
con->setHost("some.host.com", QHttp::ConnectionModeHttps);
con->get("/index.html");
// connect to QHttp's done() signal and read the response

Particularily interesting to note here is that the QIODevice (in my case the QFile instance) has to be opened explicitely before it is given to QSslCertificate. I did not do this previously, Qt neither gave me a warning nor an error, but simply refused to verify my server certificate, just because it didn’t load the root certificate properly.

(*) One could, of course, check the exact triggered SSL error from QSslError::error(), in our case this could be f.e. QSslError::UnableToGetLocalIssuerCertificate, but this is rather hacky and could certainly be abused by a man in the middle as well.