How to configure SSL for Axis2/C clients

Preamble

This tutorial tries to explain the usage of SSL client with client authentication in Apache Axis2/C. We will demonstrate a complete user scenario where the server is installed as a module on Apache2 webserver. We use our own certificate authority (CA) to issue certificates for both the client and the server.

Prerequisites

In this tutorial we assume that you have already installed Apache2 webesrver (we used version 2.2.3). Since we need to compile Axis2/C as a module for Apache2, you need to have apache development headers. These will be available if you build Apache2 from source. Also you need openssl installed.

We used openssl version 0.9.8b.

Creating the Certificate Authority

In order to provide client authentication, you need to have a CA to verify the certificates provided by the client. Even though, for a commercial web server, you would use a well known CA to obtain your certificates, when all the clients are in an intranet, if you can request other parties to trust you as a CA, or if you are the other party as in this tutorial, you can use your own CA to issue certificates. Here we assume that both the client and the server trusts only the CA that we create.

Please follow the instructions given in the Create Your Own CA and Sign Your Certificates section of the article, Create Your Own CA and Sign Your Certificates; to crate your own CA. Note that the above tutorial contains all that you need to know about creating certificates, keys, etc., that you will need here. Nevertheless, we will point to the relevant sections, as appropriate, for completeness.

Now you should have created a CA in some directory of your preference. Let's assume that it is in /home/dumindu/dummyCA.

Creating the server certificate and private key

Now that you have your own CA, next step is to create a certificate for your server, which is yet to be installed. Again refer to the above mentioned tutorial [link] for a detailed discussion. Here we include the steps you need to perform.

First we create the private key for the server.

%openssl genrsa -out server.key 1024

It will create a private key and store it in a file named server.key, which is not protected with a passphrase. If you want your key to be protected with a passphrase, please add one of "-des", "-des3", or "-aesXXX" option to the above command. Please refer to openssl documentation for a full list of supported encryption algorithms.

%openssl genrsa -des3 -out server.key 1024

Now we have to create the certificate request that has to be sent to the CA (which is our own for this tutorial).

%openssl req -new -key server.key -out newreq.pem

Copy the certificate request file, newreq.pem to your CA directory and obtain the server certificate.

%cp newreq.pem /home/dumindu/dummyCA/
%./CA.pl -sign

You should be able to find your certificate file newcert.pem in the demoCA folder.

NOTE: You should be extremely cautious about your private key and make sure that it can only be accessed by yourslef.

Deploying Axis2/C as a module in Apache2 web server.

Download Axis2/C source from the svn. AXIS2/C site contains the details: http://ws.apache.org/axis2/c/svn.html#checkout

%svn co http://svn.apache.org/repos/asf/webservices/axis2/trunk/c ~/axis2/c

NOTE: 0.96 release of Axis2/C doesn't include the files that are needed to enable the ssl transport. Client authentication is also a post-0.96 feature. Though this is relevant only to the client, we recommend that you check out the latest source to avoid any issues.

Now we have the Axis2/C source code in ~/axis2/c folder. Next is to change the directory to that folder and build the apache module.

%cd ~/axis2/c
%./configure --with-apache2=~/httpd-2.2.3/deploy/include --prefix=`pwd`/deploy-apache
%make
%make install

This will install the Axis2/C apache module (libmod_axis2.so.0.0.0) into the ~/axis2/c/deploy-apache/lib directory

Rename the Axis2/C module to mod_axis2.so and copy it to the apache modules folder.

%cp libmod_axis2.so.0.0.0 ~/httpd-2.2.3/deploy/modules/mod_axis2.so

Now we have to edit Apache2 configuration files to add axis2/c module. The following directives will do the job.

Axis2RepoPath /home/dumindu/axis2/c/deploy-apache/
Axis2LogFile /tmp/axis2.log
Axis2LogLevel info
LoadModule axis2_module /home/dumindu/httpd-2.2.3/deploy/modules/mod_axis2.so
<Location /axis2>
    SetHandler axis2_module
</Location>

NOTE: Please change the paths to suite your system.

Enable SSL in Apache2 web server

This may sometimes make confusion for the novice apache users, due to various ways Apache2 configuration is done in various distributions. Since we use the source distribution of Apache2, here we show how you can configure for the Apache2 server built from the source. Please refer to your distribution's documentation or search the web for Apache2 SSL configuration. You will find a myriad of tutorials just on that topic.

If you built apache from source, you will find a sample with SSL configuration in the conf/extra/httpd-ssl.conf file. Include this file in the conf/httpd.conf file using the following directive.

Include conf/extra/httpd-ssl.conf

Then edit the conf/extra/httpd-ssl.conf file to include the following:

Listen 9090 
SSLPassPhraseDialog builtin
<VirtualHost _default_:9090>
    DocumentRoot "/home/dumindu/httpd-2.2.3/deploy/htdocs"
    ServerName dumindu:9090 
    ServerAdmin dumindu@wso2.com 
    ErrorLog /home/dumindu/httpd-2.2.3/deploy/logs/error_log 
    TransferLog /home/dumindu/httpd-2.2.3/deploy/logs/access_log 
    SSLEngine on
    SSLCertificateFile /home/dumindu/httpd-2.2.3/certs/server.crt
    SSLCertificateKeyFile /home/dumindu/httpd-2.2.3/certs/server.key
    SSLCACertificateFile /home/dumindu/dummyCA/demoCA/cacert.pem 
    SSLVerifyClient required
    SSLVerifyDepth 1 
</VirtualHost>

Building Axis2/C client with SSL enabled

If you followed the tutorial this far, now you should be having a ssl enabled Apache2 server with Axis2/C deployed as a module. However, you will not be able to look at the deployed services using a web browser as usual. This is due to the fact that we have enabled client authentication and the server expects the client to send a client certificate when it negotiates the connection. Though we do not go into details of configuring the browser to handle such requests, what needs to be usually done is to create a .pfx file containing the client certificate and the client private key, and import that .pfx file from the browser. Also you may want to add your CA as a browser's trusted CA. Refer to your preferred browser's documentation for more details in this regard.

So we have the server configured, let's see how the client should be built so that it can handle SSL requests.

We use the same svn checkout of the Axis2/C source to build the client. However, you can use a separate checkout of the source. What matters here is that you have a separate repo for the client (we make that distinction here by deploying the server in a directory named deploy-apache and the client in a directory named deploy-client).

Since we use the same svn checkout to build the client, first thing to do is to get rid of all the binaries of the previous build. Hence, we do a dist-clean as follows.

%make dist-clean

To build Axis2/C with SSL support all you have to do is to add --enable-openssl=yes option when you run the configure script.

%./configure --prefix=`pwd`/deploy-client --enable-openssl=yes
%make
%make install

Creating client certificate and private key

Creation of the client certificate and private key is analogous to that of the server as we have done above. Replace every instance of "server" with "client" there and copy the resulting client.key and client.crt to a directory. Here again it should be stressed that the client key should always be protected against possible theft (make it only readable by you).

Axis2/C SSL Client requires the client certificate and private key to be in a certificate chain file. This can easily be created by issuing the following command, form the directory where you have copied the client certificates.

%cat client.crt client.key > client.pem

Configuring the SSL client

You can enable the SSL transport for Axis2/C client by adding the following in the client-repo's axis2.xml file.

<transportSender name="https" class="axis2_http_sender">
    <parameter name="PROTOCOL" locked="false">HTTP/1.1</parameter>
</transportSender>

Well, now we have the SSL support in our Axis2/C client, we have to configure it with the certificates, private keys and the passphrase. The SSL client accepts the following parameters:

SERVER_CERT - the file containing the CA certificate
KEY_FILE - certificate chainfile containing the client certificate and the private key
SSL_PASSPHRASE - passphrase used to encrypt the private key file

Setting these parameters can be done in two different ways. First is to set them in the axis2.xml file. For example, in our sample, the following was added to the axis2.xml.

<parameter name="SERVER_CERT">/home/dumindu/dummyCA/demoCA/cacert.pem</parameter>
<parameter name="KEY_FILE">/home/dumindu/axis2/c/deploy-client/client.pem</parameter>
<parameter name="SSL_PASSPHRASE">abc123</parameter>

Second way of setting these values is programmatically in the client program itself as follows:

ssl_ca_file = axis2_property_create(env);
AXIS2_PROPERTY_SET_VALUE(ssl_ca_file, env,
		axis2_strdup("/home/dumindu/dummyCA/demoCA/cacert.pem", env));
AXIS2_OPTIONS_SET_PROPERTY(options, env, "SERVER_CERT", ssl_ca_file);

You set the other properties in the same lines as above. You can find the complete sample code here.

How to use client authentication in wsf4php

You can use the following options available in WSClient options array to specify CA certificate , client certificate chain file and passphrase.

e.g.

"CACert"  => /home/dumindu/dummyCA/demoCA/cacert.pem
"clientCert" =>/home/dumindu/axis2/c/deploy-client/client.pem

"passphrase" => abc123

Then use an "https://" endpoint and ssl will be automatically selected.

Sample Code.

$client = new WSClient(
		array("to"=>"https://10.100.1.143:9090/axis2/services/echo", 
		      "CACert"=>"/home/dumindu/dummyCA/demoCA/cacert.pem", 
		      "clientCert"=>"/home/dumindu/axis2/c/deploy-client/client.pem", 
		      "passphrase"= "abc123")
		);