MS SoapClient and WSDLReader error ‘80020009’

This trips me up every year with a blob of legacy classic ASP code I have on my debug and test environment:

wsdl = ""
Set service = CreateObject("MSSOAP.SoapClient30")
service.ClientProperty("ServerHTTPRequest") = True
Call service.MSSoapInit(wsdl)

The above code suddenly starts throwing this error for no apparent good reason:

WSDLReader error '80020009'

WSDLReader:XML Parser failed at linenumber 0, lineposition 0, reason is: System error: -2147012721. HRESULT=0x1: Incorrect function. - WSDLReader:Loading of the WSDL file failed HRESULT=0x80070057: The parameter is incorrect. - Client:One of the parameters supplied is invalid. HRESULT=0x80070057: The parameter is incorrect.

/services/, line 5

Then after half an hour of head scratching I realise the SSL certificate has probably expired…and lo and behold it has.

Maybe next year the penny will drop more quickly. :)

Posted in IIS7 | Leave a comment

Mercurial and mercurial-server on CentOS

In my previous two posts I explained how I configured Python 2.7 and Mercurial 1.9.3 on CentOS 5.5 x64 for HTTP access. HTTP access is fine but life is simpler when using SSH.

mercurial-server is one of many shared SSH publishing solutions to allow your development team have access to your central repository collection.

It kind of works like this. A single SSH account (hg) is created on your Mercurial central repo server. This account acts as a gateway account and it also owns all of the repositories on the server. The account is heavily restricted. You can’t logon to it using a username and password, only SSH keys are permitted and these keys must be imported using mercurial-server’s refresh-auth script (or via upload to a special administrative repository once the administrator’s public key has been installed).

Each developer generates a public and private SSH key pair. Their public key is uploaded to central repository server and is added to the hg account’s ~hg/.ssh/authorized_keys file using the refresh-auth script (or via the hgadmin administrative repository.

Each authorized_keys record also has the command option specified which restricts the hg logon to a single operation regardless of any commands specified by the client (which are ignored). For example:

no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,command="/usr/local/share/mercurial-server/hg-ssh root/bob/" ssh-dss AAAAB3NzaC1kc...Qfa02w==

For a more detailed explanation of how this works see: How mercurial-server works

First off, download and unzip mercurial-server from here:

mercurial-server 1.2 sources

tar zxf mercurial-server_1.2.tar.gz
cd mercurial-server_1.2.orig

Before building and installing there’s some tweaks I needed to make for my CentOS install.

On CentOS we need to prevent the docbook files being built. They’re not necessary and the build will fail on CentOS if you try to build them.

Open up Makefile, at around line 53 you’ll see this step:

installfiles: installetc installdoc pythoninstall 

I removed the installdoc reference, so it should look like this:

installfiles: installetc pythoninstall 

Next we need to amend the useradd command switches at around line 61. CentOS doesn’t support the --system switch and we need to use -r instead:

        useradd -r --shell /bin/sh \
            --home /var/lib/mercurial-server --create-home \
            --comment  "Mercurial repositories" $(NEWUSER)

Finally, because I have both Python 2.4 and 2.7 installed and my Mercurial installation has been installed for Python 2.7, I need to ensure that Python 2.7 is called.

To make this easier I modified the Makefile just a bit more and added a PYTHON variable to point to the default version of python I want to use. This is because make doesn’t expand bash aliases, so even if you’ve aliased python to Python 2.7 it’ll be ignored. Setting a PYTHON variable and using that makes life easier. It also means you can override the python version from the command line. This is my revised Makefile:

#!/usr/bin/env make -f



build: build/html/index.html pythonbuild

setup-adduser: installfiles adduser inituser

# WARNING: this is experimental
setup-useradd: installfiles useradd inituser

        rm -Rfv $(DESTDIR)$(ETCDIR)
        rm -Rfv $(DESTDIR)$(LIBDIR)
        userdel -rf $(NEWUSER)

        $(INSTALL) -d $(DESTDIR)$(ETCDIR)
        $(INSTALL) -m 644 -t $(DESTDIR)$(ETCDIR) \
        $(INSTALL) -d $(DESTDIR)$(ETCDIR)/remote-hgrc.d
        $(INSTALL) -m 644 -t $(DESTDIR)$(ETCDIR)/remote-hgrc.d \
            src/init/conf/remote-hgrc.d/access.rc \
        $(INSTALL) -d $(DESTDIR)$(ETCDIR)/keys/root
        $(INSTALL) -d $(DESTDIR)$(ETCDIR)/keys/users

installdoc: build/html/index.html
        $(INSTALL) -d $(DESTDIR)$(DOCDIR)
        $(INSTALL) -m 644 -t $(DESTDIR)$(DOCDIR) README
        $(INSTALL) -d $(DESTDIR)$(DOCDIR)/html
        $(INSTALL) -m 644 -t $(DESTDIR)$(DOCDIR)/html build/html/index.html

build/html/index.html: doc/manual.docbook
        xsltproc --nonet -o $@ $(DOCBOOK_XSL)/html/docbook.xsl $^

build/pdf/manual.pdf: doc/manual.docbook
        mkdir -p build/pdf
        fop -xml $^ -xsl $(DOCBOOK_XSL)/fo/docbook.xsl $@

        $(PYTHON) build

        $(PYTHON) install \
            --install-purelib=$(DESTDIR)$(LIBDIR) \
            --install-platlib=$(DESTDIR)$(LIBDIR) \
            --install-scripts=$(DESTDIR)$(LIBDIR) \

installfiles: installetc pythoninstall

        adduser --system --shell /bin/sh --group --disabled-password \
            --home /var/lib/mercurial-server \
            --gecos  "Mercurial repositories" $(NEWUSER)

# WARNING: this is experimental
        useradd -r --shell /bin/sh \
            --home /var/lib/mercurial-server --create-home \
            --comment  "Mercurial repositories" $(NEWUSER)

        su -l -c "$(DESTDIR)$(LIBDIR)/init/hginit $(DESTDIR)$(LIBDIR)" $(NEWUSER)

I also added a remove rule to clean up and remove mercurial-server so you can do make remove. I left the docbook rules in place because one day I might get around to fixing that for CentOS, however they don’t get called.

All that remains now is to build and install mercurial-server, do this by running:

make setup-useradd

The first thing we need to do is generate and install the administrators SSH public and private key pairs. If you already have a pair of key files you want to use then skip the next step:

To generate a new public/private key pair then use ssh-keygen:

[root@vostro1700 ~]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): kevin_rsa
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in kevin_rsa.
Your public key has been saved in
The key fingerprint is:
[root@vostro1700 ~]#

You can do this on the mercurial server machine or you can do this on your workstation. Ultimately we want to get the public key file ( onto the server.

Once you’ve generated a pair of key files and you’ve got the public key file onto the mercurial server we need to copy it to the mercurial-server keys/root folder and then instruct mercurial-server to “import” it to the hg user’s authorized_keys file:

sudo mkdir -p /etc/mercurial-server/keys/root/kevin
sudo cp /etc/mercurial-server/keys/root/kevin
sudo -u hg /usr/local/share/mercurial-server/refresh-auth

We’re now ready to create new repositories.

Connecting From Linux
If your client machine is Linux and you’re already using SSH keys to authenticate against remote servers then the following will be familiar. First we start ssh-agent, then we add our private key. This means we don’t have to re-type our password:

$ eval `ssh-agent`
Agent pid 13464

What we just did there was launch ssh-agent but evaluate the output, this sets up a couple of handy environment variables (SSH_AUTH_SOCK and SSH_AGENT_PID). If we just did ssh-agent on its own then we’d see:

SSH_AUTH_SOCK=/tmp/ssh-RnDfd13515/agent.13515; export SSH_AUTH_SOCK;
echo Agent pid 13516;

Next we need to add our private key:

$ ssh-add kevin_rsa
Enter passphrase for kevin_rsa:
Identity added: kevin_rsa (kevin_rsa)

Finally lets see if we can create a new repository on the remote server:

$ hg init ssh://

If all is well then you should see a helloworld folder appear in /var/mercurial-server/repos.

Connecting From Windows – TortoiseHg
On my Windows Workstation I have the Selenic TortoiseHg bits installed. I also have PuTTY and its related tools installed as well because I use PuTTY but I also need PuTTYgen as well.

There’s a bit of a gotcha with PuTTY and SSH key files. If you generated your keyfiles using ssh-keygen then they need to be converted to work with PuTTY and Pageant (PuTTY’s equivalent of ssh-agent).

To do this launch PuTTYgen and select “Conversions -> Import key”:

Locate your private key file (kevin_rsa) which was generated using ssh-keygen and open it. You’ll be prompted for the private key’s password, enter it and hit enter. If the key file is imported successfully then PuTTYgen will pop up a notice and tell you what to do next:

Click OK and then click on “Save private key”, I saved mine as “kevin_rsa_putty.ppk” (the PuTTY tools like to see the .ppk extension so you may as well go along with that).

As an aside I save my keys in a hidden “.ssh” folder in my %USERPROFILE% folder.

As I mentioned earlier, Pageant does the equivalent job of ssh-agent. When you launch Pageant it’ll minimise itself into the notification area:

Load up your newly converted private key into Pageant by right clicking on it’s icon and selecting “Add Key”:

You’ll prompted for your private key file’s password so enter it and hit enter. To confirm the key is loaded right click on Pageant’s notification icon and select “View Keys”. All being well we should see our key in the key list:

Next we need to tell TortoiseHg about our SSH settings. In your Windows %USERPROFILE% directory there should be a file called mercurial.ini. If there isn’t then create one. Mine looks like this:

ui.language = en_GB
vdiff = kdiff3

merge = kdiff3
username = kevin <>
verbose = True
ssh="C:\Program Files\TortoiseHg\TortoisePlink.exe" -ssh -2 -agent -v

The important line line is the one that says:

ssh="C:\Program Files\TortoiseHg\TortoisePlink.exe" -ssh -2 -agent -v

TortoisePlink.exe is a recompiled variant of PuTTY’s Plink tool. Plink is the equivalent of Unix’s ssh tool.

That line is instructing TortoiseHg to connect to our remote Mercurial server using TortoisePlink and pickup our private key along the way from Pageant.

Save mercurial.ini and then open a command line window. Next try to create a new repository on your remote Mercurial server (I have all the verbosity switches turned on just so we can see what’s happening under the bonnet):

hg init ssh://

This should result in output that looks similar to this:

running "C:\Program Files\TortoiseHg\TortoisePlink.exe" -ssh -2 -agent -v "hg init anewrepo"
running ""C:\Program Files\TortoiseHg\TortoisePlink.exe" -ssh -2 -agent -v "hg -R anewrepo serve --stdio""
remote: Looking up host ""
remote: Connecting to port 22
remote: Server version: SSH-2.0-OpenSSH_4.3
remote: We claim version: SSH-2.0-PuTTY_Local:_Feb_27_2009_19:14:38
remote: Using SSH protocol version 2
remote: Doing Diffie-Hellman group exchange
remote: Doing Diffie-Hellman key exchange with hash SHA-1
remote: Host key fingerprint is:
remote: ssh-rsa 2048 6f:23:ab:c8:4a:12:8a:d9:b0:36:09:b4:49:54:97:c0
remote: Initialised AES-256 SDCTR client->server encryption
remote: Initialised HMAC-SHA1 client->server MAC algorithm
remote: Initialised AES-256 SDCTR server->client encryption
remote: Initialised HMAC-SHA1 server->client MAC algorithm
remote: Pageant is running. Requesting keys.
remote: Pageant has 1 SSH-2 keys
remote: Using username "hg".
remote: Trying Pageant key #0
remote: Remote debug message: Pty allocation disabled.
remote: Remote debug message: Port forwarding disabled.
remote: Remote debug message: X11 forwarding disabled.
remote: Remote debug message: Agent forwarding disabled.
remote: Remote debug message: Forced command: /usr/local/share/mercurial-server/hg-ssh root/kevin/
remote: Authenticating with public key "imported-openssh-key" from agent
remote: Sending Pageant's response
remote: Remote debug message: Pty allocation disabled.
remote: Remote debug message: Port forwarding disabled.
remote: Remote debug message: X11 forwarding disabled.
remote: Remote debug message: Agent forwarding disabled.
remote: Remote debug message: Forced command: /usr/local/share/mercurial-server/hg-ssh root/kevin/
remote: Access granted
remote: Opened channel for session
remote: Started a shell/command
remote: Sent EOF message
remote: Server sent command exit status 0
remote: Disconnected: All channels closed

Logon to your repository server and look in the /var/lib/mercurial-server/repos folder, there should be a new directory in there called anewrepo.

A Gotcha: When running Pageant and TortoiseHg, make sure that if you run either as “Administrator”, both run as administrator. I had an hour or so of head scratching when running hg init ssh:// from an command prompt opened using “Run As Administrator” whilst Pageant was running under my normal Windows account.

In the next article I’ll cover adding new users and joining up the mercurial-server repository with Apache.

Very useful resources:

Sharing Mercurial repositories with mercurial-server
Using ssh-agent with ssh
Using Pageant for authentication

Posted in Mercurial, Python | 1 Comment

Another Python/Mercurial/mod_wsgi on CentOS HOWTO – 2/2

In part 1 I covered how to install Python, Mercurial and mod_wsgi. In this article I’ll explain how to publish your repositories.

Configure Apache + mod_wsgi
Load up your apache httpd.conf file into your favourite editor and add the following lines:

LoadModule wsgi_module modules/
AddHandler wsgi-script .wsgi
WSGIPythonHome /opt/python2.7.2

That last line ensures that mod_wsgi knows which Python to invoke.

On my system I’m using named virtual hosts, this is what my Mercurial’s site virtual host configuration looks like:

 ServerName mercurial
 ServerAdmin root@localhost
 DocumentRoot /sites/mercurial/htdocs
 WSGIScriptAlias / /sites/mercurial/htdocs/cgi-bin/hgweb.wsgi

Under your document root create a folder called cgi-bin and create a file in there called hgweb.wsgi.

To verify that mod_wsgi is working I used the trouble-shooting script found on the “Installation Issues” section of the mod_wsgi site. So drop that code into the newly created hgweb.wsgi file and save it:

import sys

def application(environ, start_response):
    status = '200 OK'
    output = 'Hello World!'

    response_headers = [('Content-type', 'text/plain'),
                        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)

    print >> sys.stderr, 'sys.prefix = %s' % repr(sys.prefix)
    print >> sys.stderr, 'sys.path = %s' % repr(sys.path)

    return [output]

When you browse to your site you should see: Hello World! in my browser. So far so good.

Mercurial Configuration
If the above works then replace the contents of hgweb.wsgi with the following:

# An example WSGI for use with mod_wsgi, edit as necessary
# See for more information

# Path to repo or hgweb config to serve (see 'hg help hgweb')
config = "/sites/mercurial/htdocs/cgi-bin/hgweb.config"

# Uncomment and adjust if Mercurial is not installed system-wide:
#import sys; sys.path.insert(0, "/path/to/python/lib")

# Uncomment to send python tracebacks to the browser if an error occurs:
#import cgitb; cgitb.enable()

# enable demandloading to reduce startup time
from mercurial import demandimport; demandimport.enable()

from mercurial.hgweb import hgweb
application = hgweb(config)

You can find this file in the Mercurial source in the contrib folder. If you’ve followed my instructions to the word

Next create a new file in the cgi-bin folder called hgweb.config and add the following:

/ = /sites/mercurial/htdocs/repos/**
allow_push = *
push_ssl = false

Create a folder for your repositories under your document root and initialise a new repository:

mkdir repos
cd repos
hg init testrepo

You should now be able open the Mercurial repository browser by opening:

You also need to ensure that your web server’s user can read and write to your repositories. On a default apache install on CentOS this should look like:

chown -R apache:apache /sites/mercurial/htdocs/repos
chmod -R g+rw /sites/mercurial/htdocs/repos
chmod g+x /sites/mercurial/htdocs/repos

You also need to make each repository folder and it’s .hg folder executable as well:

chmod g+x /sites/mercurial/htdocs/repos/testrepo
chmod g+x /sites/mercurial/htdocs/repos/testrepo/.hg

For more info see: Mercurial – 8. Troubleshooting

To test your Mercurial server go to a different machine and do:

E:\>md hg_test

E:\>cd hg_test

E:\hg_test>hg clone
destination directory: testrepo
no changes found
updating to branch default
resolving manifests
0 files updated, 0 files merged, 0 files removed, 0 files unresolved

E:\hg_test>cd testrepo

E:\hg_test\testrepo>copy con test.txt
Hello World!
        1 file(s) copied.

E:\hg_test\testrepo>hg add test.txt
adding test.txt

E:\hg_test\testrepo>hg commit test.txt -m "Test commit"
committed changeset 0:1904a8ab9a97

E:\hg_test\testrepo>hg push
pushing to
searching for changes
1 changesets found
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 1 changes to 1 files


If we browse to our repository we can see the file we just pushed:

If you follow all of the steps exactly you should end up with a basic but working Mercurial server that you can use to push and pull changesets to.

Obviously you should secure this server if it’s public facing (mine is secured with a simple .htaccess/.htpassword affair for now).

There were a number of sites and documents online that helped me to get this far, these included:

The following Mercurial articles also helped:

Posted in CentOS, Mercurial, Python | Leave a comment

Another Python/Mercurial/mod_wsgi on CentOS HOWTO – 1/2

This is how I got Mercurial up and running on CentOS 5.5 x64. The goal here was to deploy this as a “central” repository Mercurial server so the dev team can push their updates to this box.

For this build I used:

Python 2.7.2
PyPi Setup Tools 0.6c11
mod_wsgi 3.3
Docutils 0.8.1
Mercurial 1.9.3

First off download all of the files listed above to /usr/local/src:

cd /usr/local/src
tar zxf Python-2.7.2.tgz
tar zxf sqlite-autoconf-3070800.tar.gz
tar zxf mod_wsgi-3.3.tar.gz
tar zxf docutils-0.8.1.tar.gz
tar zxf mercurial-1.9.3.tar.gz

Install Dependencies
There are a few dependencies we’ll need, some might already be installed:

yum -y install gcc gdbm-devel readline-devel ncurses-devel zlib-devel bzip2-devel sqlite-devel db4-devel openssl-devel tk-devel bluez-libs-devel make

Build and install SQLite3:

cd sqlite-autoconf-3070800
make install
cd ..

CentOS 5.5 ships with Python 2.4 which is fine for Mercurial but I wanted to use Python 2.7 for some other stuff as well. This explains how to install Python 2.7 side by side with 2.4 (which would be a real bugger to evict from your system due to the huge number of dependencies there are – yum for example).

I installed Python 2.7 into /opt/python2.7.2, to do this:

cd Python-2.7.2
./configure --prefix=/opt/python2.7.2 --with-threads --enable-shared
make install
cd ..

When you execute make it’s possible you’ll get this message:

Python build finished, but the necessary bits to build these modules were not found:
bsddb185 dl imageop

Don’t worry, Python was built successfully, it just means these modules aren’t supported. For our purposes it won’t break anything not to have these modules, they are either deprecated or not relevant.

Next we need to tell ld where to find our Python 2.7 shared libraries:

touch /etc/
echo "/opt/python2.7.2/lib/" >> /etc/

Then we create a link to Python 2.7 in /usr/bin and fix up our bash profile to use 2.7:

ln -sf /opt/python2.7.2/bin/python /usr/bin/python2.7
echo "alias python=/opt/python2.7.2/bin/python" >> ~/.bash_profile
echo "alias python2.7=/opt/python2.7.2/bin/python" >> ~/.bash_profile
echo "PATH=$PATH:/opt/python2.7.2/bin" >> ~/.bash_profile
source ~/.bash_profile

If all is well you should see the following when you launch python:

Python 2.7.2 (default, Oct 21 2011, 10:46:56)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-51)] on linux2
Type "help", "copyright", "credits" or "license" for more information.

Press Ctrl+D to exit back to bash.

PyPi, pip, virtualenv (optional)
Although not strictly necessary I also installed these to flesh out my Python dev environment:

cd /usr/local/src
sh setuptools-0.6c11-py2.7.egg --prefix=/opt/python2.7.2
/opt/python2.7.2/bin/easy_install pip
ln -sf /opt/python2.7.2/bin/pip /usr/bin/pip
pip install virtualenv
ln -sf /opt/python2.7.2/bin/virtualenv /usr/bin/virtualenv

Mercurial requires Docutils. When installed this for the first time I had to explicitly call python 2.7 to ensure that Docutils was installed to /opt/python2.7 and not the default Python 2.4 install (that said it’s no big deal if it does also end up being installed there):

cd docutils-0.8.1
python2.7 install
cd ..

Drop into the mercuria source directory:

cd mercurial-1.9.3

Build and install Mercurial:

make PYTHON=/opt/python2.7.2/bin/python PREFIX=/opt/python2.7.2 all
make PYTHON=/opt/python2.7.2/bin/python PREFIX=/opt/python2.7.2 install
cd ..

Pay particular attention to the PYTHON=/opt/python2.7.2/bin/python and PREFIX=/opt/python2.7.2 arguments, these ensure that mercurial is built using our Python 2.7 install and gets installed in the correct site-packages folder.

Enter hg version and hit return, if all is good you should see:

Mercurial Distributed SCM (version 1.9.3)
(see for more information)

Copyright (C) 2005-2011 Matt Mackall and others
This is free software; see the source for copying conditions. There is NO

To build mod_wsgi you need to ensure that the httpd-devel package is installed, I’m assuming you already have apache installed, so go ahead and do that now:

yum install httpd-devel

Next we do the build, and be sure to configure for Python 2.7:

cd mod_wsgi-3.3
./configure --with-python=/opt/python2.7.2/bin/python
make install

If all is good then you’ll find in your apache modules folder:

$ ll /usr/lib/httpd/modules/
-rwxr-xr-x 1 root root 303801 Oct 21 12:12 /usr/lib/httpd/modules/

Continued in Part #2…

Posted in Uncategorized | 2 Comments


My old DasBlog based site got a bit tired and too hard to maintain so here’s a blog reboot.

Posted in Uncategorized | 1 Comment