I was excited to learn recently that the Nokia N73 can speak AtomPub, and that a friend of mine owns one. I thought I'd try to make it talk to the new AtomPub implementation in WordPress, but reading through the N73 documentation I found that it only supports WSSE authentication, and WordPress only speaks HTTP Basic Authentication. I'd never heard of WSSE, but Mark Pilgrim has a good write up on XML.com, and the Ape has the ability to speak WSSE, so I thought I'd implement it in WordPress. Bear in mind that I'm not writing this from a security point of view, I'm just looking at authentication as a necessary evil to get cool AtomPub things working. And there's a spoiler: it can't be done :)

A WSSE client will send an Authorization header which, as we know, will get dropped if Apache is passing the request off to a CGI, and a X-WSSE header that looks like this:X-WSSE: UsernameToken Username="USERNAME", PasswordDigest="PASSWORDDIGEST", Nonce="NONCE", Created="2007-09-08T05:52:36Z"

PasswordDigest is a base64 encoded SHA1 digest of the concatenation of the nonce, the timestamp and the password. The nonce is of course some random string.

So, to add WSSE into WordPress AtomPub, we can add some code to the authentication function in wp-app.php.

First, we check if the client is trying to authenticate using WSSE by looking for a X-WSSE header.if(isset($username_token = $_SERVER['HTTP_X_WSSE'])) {

We then take the Username Token contained therein and split out the user, digest, nonce, created information sent by the client. There are probably nicer ways to do this. $wsse = array( 'user' => "", 'digest' => "", 'nonce' => "",
'created' => "", 'password' => "");
$tokens = explode(", ", trim(strstr(stripslashes($username_token), " ")));
foreach ($tokens as $token) {
$pivot = strpos($token, '=');
$key = substr($token, 0, $pivot);
$value = trim(substr($token, $pivot + 1), '"');
switch ($key) {
case "Username":
$wsse['user'] = $value;
break;
case "PasswordDigest":
$wsse['digest'] = $value;
break;
case "Nonce":
$wsse['nonce'] = $value;
break;
case "Created":
$wsse['created'] = $value;
break;
}
}

Finally, we recreate the digest on the server, and compare it to what was sent, and close the if. $wsse['password'] = get_password_by_login($wsse['user']);
$server_digest = base64['encode(pack("H*", sha1($wsse['nonce'] . $wsse['created'] . $wsse['password'])));
if ($server_digest == $wsse['digest']) {
$login_data = array('login' => $wsse['user'], 'password' => $wsse['password']);
}
}

If you have familiarity with WordPress's code, you might be saying something like, "WTF is this get_password_by_login() function call? I've never seen such a thing!" Good question. And the dirty little secret is that no such function exists. A weakness of the WSSE authentication scheme appears to be that to recalculate the digest the password needs to be stored in plain text on the server. This is probably at least as bad as sending the password in plain text over the wire, the thing that WSSE is trying to avoid. WordPress, sensibly, does not store passwords in plain text, but computes an md5 hash of them and stores that.

So, as far as I can tell, there is no way to implement WSSE in WordPress in any sensible way.

One little word on security. If we could implement WSSE, the code should keep track of nonces and make sure they aren't repeated, and should reject UsernameTokens created more than a couple of minutes ago (leaving aside any discussion of synchronisation of your client's clock with my server).

P.S. I hadn't read Joe Cheng's comment or Joseph Scott's reply in the comments of the post I linked to above before I started off on this wild goose chase.

I mentioned previously that the AtomPub server in my WordPress installation wasn't successfully deleting entries. More specifically, I get a 403 Forbidden when trying to PUT or DELETE posts or media files. I posted to the wp-testers mailing list and Joseph Scott passed the question along to Sam Ruby, Tim Bray, Elias Torres, and Pete Lacey, and I basically eavesdropped on their conversation....

[read more]
In HTML whitespace is not treated as significant, and therefore it gets collapsed. This is a problem when you want to publish code because your indenting will disappear. The most common way around this is to wrap code in a pre element, but that looks like crap because it's always the default monospace font, and you can't style it. A better way is to use CSS, specifically white-space: pre;. In WordPress, log in to the admin section, click Presentation and select Theme Editor. Choose Stylesheet from the list on the right, then look for the code declaration. Add ...
[read more]
I've posted a small WordPress AtomPub FAQ. It's a temporary home until I can find somewhere sensible to put it. If you have anything you'd like to add or correct or mock, comment here. If you can offer a sensible place to put it, let me know.
The WordPress 'new post' bookmarklet lets you highlight some text on a page, run the bookmarklet and redirects you to your admin new posts page with the title prefilled with the title of the page you were on and the content prefilled with a link to the page you were on and the text you had highlighted. However, the default layout isn't the way I like to do quote posts, so I had a poke around to find out how to change it. In the file wp-admin/admin-functions.php there is a function get_default_post_to_edit(). Midway through the function the variable $post_content...
[read more]
So, WordPress 2.3 beta adds support for AtomPub. All good. I installed it (separately to this blog, I'm just playing around), but all I could get out of the APE was a 401, even though I'd provided the correct authentication credentials. Looking at the code, with liberal use of the logging therein, I worked out that PHP_AUTH_* weren't being set, so I pulled out some auth code and tried it on it's own. No luck. Weird. I then grabbed a previously working snippet and tried that, but it was broken too. On both the servers to which I have ...
[read more]
WordPress 2.1.1 is dangerous, upgrade to 2.1.2 immediately. Some malicious code has been injected into the WordPress 2.1.1 code, and an immediate upgrade is urged. Notify all your friends and relatives. Follow the upgrade directions in the WordPress documentation, and the process is pretty simple. I even left this post written and unposted, then posted after the upgrade and everything was fine.
My problem importing my blogroll had nothing to do with an invalid OPML file, there is a bug in WordPress. The file imports correctly when imported from a URL, but not from a file.
So, now links work. I had decided to change the permalink mode from the "ugly" default to "almost pretty", which makes permalinks look like http://www.twofishcreative.com/michael/blog/2007/02/27/wordpress-woes/. What I didn't do was create an .htaccess file so that WordPress could use apache's mod_rewrite to make sure that those almost pretty links actually work. All I needed to do was ssh to my host, change to my blog directory and touch .htaccess chmod 666 .htaccess Then when I chose the almost pretty permalink option WordPress updated the .htaccess file to include the necessary rewrite rules. More information can be found under the Wordpress ...
[read more]
Okay, this isn't going so well. I've edited the About page, and now I get a 404 on it. I'm sure it worked before, and all I did was edit content. And none of the category links are working either. I started mucking with the theme code, I'm pretty knackered at the moment, and that's not the best time to start hacking with themes, but I can't see that I would have done anything bad. I'm not sure what I broke. [Update: hmm, not even the links to posts work]