# Revisiting Mercurial and file keyrings

In a previous post I talked about setting up an encrypted file based keyring store for Mercurial. With some recent updates of the Python keyring modules, the setup changed a little bit again.

The file-backed keyrings got moved out to the keyrings.alt package. $HOME/.local/share/python_keyring/keyringrc.cfg needs to be adjusted as follows: [backend] default-keyring=keyrings.alt.file.EncryptedKeyring # Mercurial, python keyring 3, and mercurial keyring In an earlier post I documented how to set up an encrypted file store for your keyring. With recent versions of Python keyring (at least 3 and up) the CryptedFileKeyring backend got removed and replaced by EncryptedKeyring. So in your $HOME/.local/share/python_keyring/keyringrc.cfg you need to now have the following:

[backend] default-keyring=keyring.backends.file.EncryptedKeyring

# Mercurial and safely storing passwords

Mercurial allows for tying in keyring configuration for those of us who do not want to store passwords in plain-text in our .hgrc files or constantly using SSH.

First install the Python keyring library by running pip install keyring. After that is installed, checkout https://bitbucket.org/Mekk/mercurial_keyring/ and add to $HOME/.hgrc the following: [extensions] mercurial_keyring = ~/path/to/mercurial_keyring/mercurial_keyring.py Next up, configure your repositories, e.g. in the case of Bitbucket I use: [auth] bitbucket.prefix = bitbucket.org/asmodai bitbucket.username = asmodai bitbucket.schemes = https Mercurial keyring will automatically decide on the best keyring to use. On a FreeBSD system with no Gnome or other systems providing a keyring, if you do not specify a specific keyring, the system will use the file ~/.local/share/python_keyring/keyring_pass.cfg. This keyring file stores the passwords encoded in Base64 in plain-text. This is not quite what you would want from a security point of view. You can configure which backend store to use by editing $HOME/.local/share/python-keyring/keyringrc.cfg. To get a plain-text file with encrypted keys use the following configuration:

[backend] default-keyring=keyring.backend.CryptedFileKeyring

This will create the file ~/.local/share/python-keyring/crypted_pass.cfg after initializing the backend store with a password. Look at the documentation for keyring on what other configuration options are available.

Note: make sure the PyCrypto dependency is installed with the _fastmath module. This in turn depends on the gmp library.

# JSONP with Werkzeug

So I had implemented a simple JSON data server with Werkzeug for a classroom experiment. Unfortunately in my haste to get everything up and running I totally forgot about the fact that, since we cannot allow uploads to this server of various custom made webpages, using jQuery’s $.ajax() everything just fails since it will then be a cross-site scripting request. So, normally you would do something like the following in order to return JSON data: return json.dumps(data) Which would be used with the$.ajax() call in a way like the following:

$.ajax({ type: "POST", url: "http://example.com/json/something", data: "parameter=value", dataType: "json", error: function(XMLHttpRequest, textStatus, errorThrown){}, success: function(data, msg){} }); Which is perfectly fine for scripts getting and using the data on the same host/domain. But, as said before, this will fail with warnings similar to: "Access to restricted URI denied" code: "1012" nsresult: "0xdeadc0de (NS_ERROR_DOM_BAD_URI)". One way out of this is using JSONP. jQuery has a $.getJSON() function, which loads JSON data using a HTTP GET request. Now, the simplistic way to convert your code would be to change it as such:

$.getJSON("http://example.com/json/something", function(data){} ); But this causes another issue. Since $.getJSON() GETs the JSON data, but doesn’t use eval() on it, but instead pulls the result into script tags, it somehow causes,on Firefox at least, an invalid label error. In order to fix this you need to set up the JSON data server to properly support a callback argument, to use $.getJSON() how it is meant to be used: $.getJSON("http://example.com/json/something?jsoncallback=?", function(data){} );

In the code above the additional parameter jsoncallback will, thanks to jQuery, get the question mark replaced by an alphanumeric string (typically in the form of jsonp followed by a timestamp). This value should be used to wrap the resulting JSON data with. This means you would have to change the initial Python code to something like this:

return request.args.get('jsoncallback') + '(' + json.dumps(data) + ')'

Of course this causes problems when you want to reuse the code for both AJAX use on the same host/domain and use it from outside. So in order to make both work you can test on whether or not the callback parameter is available and return the appropriate data. I came up with this little snippet for that:

def jsonwrapper(self, request, data): callback = request.args.get('jsoncallback')   if callback: return callback + '(' + json.dumps(data) + ')' else: return json.dumps(data)

# OpenSSH ControlMaster and Subversion

OpenSSH has a fantastic feature called ControlMaster. Basically this option allows you to create a socket that will share your already opened ssh session to the same host. To enable this option for all you put the following snippet in your $HOME/.ssh/config after creating something like $HOME/.ssh/sockets:

Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h:%p

For every username@host:port it will create a socket in $HOME/.ssh/sockets. The only problem is that current Subversion (1.4.6 on my FreeBSD box) cannot work well with control sockets when using the svn+ssh:// URI identifier. In order to work around this problem you can add a specific host before the wildcard entry, for example: Host svn.example.com ControlMaster no Host * ControlMaster auto ControlPath ~/.ssh/sockets/%r@%h:%p Of course, doing it like this is a bit tedious for every Subversion repository you use in this manner. Thankfully there is another way to do this. In $HOME/.subversion/config there is a section called [tunnels]. If you add the following entry to that section it will disable the ControlMaster:

[tunnels]
ssh = ssh -o ControlMaster=no

# The cake is a lie

Some of you may have played Valve’s Portal game and remember the phrase that ‘[t]he cake is a lie’. Most of us most likely associated this with the fact you get incinerated at the end of the trials.

I think the meaning is twofold though. Remember the source code leak Valve experienced in 2003 of their Half Life 2 engine code base? It became clear during a trial in Germany in November 2006 that a group called ‘myg0t’ (a play on ‘mein Gott’?) was actually responsible for the source code leak. Now, apparently the myg0t group has some sort of initiation ritual where people have to (source: Wikipedia article on myg0t):

1. bake a cake
2. write “myg0t owns me” on it
3. take a picture of the cake with your face (including party hat) next to it
4. take a picture of you eating the cake and
5. post the picture online in a gallery

Now, given that the Orange box came out in 2007, would it be overly strange if Valve was making a reference (with the cake is a lie quote) that the ‘cake initiation’ is just a lie for them (myg0t) to laugh at others who want to join? Personally I think it fits right into Valve’s alley.