2007/10/08
8 Oct, 2007

A Quick Reference Guide for Rampart/C Configurations

  • Malinda Kaushalye
  • Tech-lead - WSO2

Introduction

Sometimes Rampart/C is used to provide the confidentiality for the messages exchanged and sometimes for user authentication etc. Depending on these different requirements, different configurations are needed to be set up both in the client and the server. Here our discussion will be limited only for the essential details that are necessary to understand these configurations.

Table of Content

Where to Define Configurations

In the client side, a policy file (policy.xml) is located along with the axis2.xml. This is usually known as the client's repository where we keep the libraries and modules on behalf of the client. This is a sample client policy file

In the server side we define our policy assertions in the services.xml. The services.xml is in the same directory where you deposited the services module, in which you keep your business logic. This is a sample services.xml file

These two configurations files are a MUST to enable WS-Security. Rampart/C behaves according to the assertions (configuration metadata) defined in those two. This behavior is two-folds. As per the assertions defined in these files,

  1. Rampart/C builds the message.
  2. Rampart/C processes/verifies the message.

In the following set of "How to" topics we will discuss above two behaviors in Rampart/C. But in order to understand WS-Security Policy we recommend you to refer the WS-Security Policy specification. Note that some assertions discussed here are alien to the specification. Those are specific to the Rampart/C, and defined in the name-space of rampc="http://ws.apache.org/rampart/c/policy. These assertions are to provide Rampart/C configurations, that cannot be achieved only with the assertions defined in the WS-Security Policy specification. For example to define where to locate the private key, we use

<rampc:PrivateKey>/path/to/private/key/my_key.pem</rampc:PrivateKey>

How to Enable Timestamps

To enable timestamps you need to add two assertions in the policy configuration. First assertion orders the inclusion of wsu:Timestamp element in the security header.

<sp:IncludeTimestamp/>

The second assertion informs how many seconds the timestamp should be valid. In other words, the time to live. This is the difference between the created time and the expiring time.

<rampc:TimeToLive>360</rampc:TimeToLive>

Note that if the signing is enabled, Rampart/C by default signs the timestamp too.

How to Add a Username Token

To add a usernametoken you need to include it under the sp:SignedSupportingTokens assertion. This is how you do it in the policy file.

<sp:SignedSupportingTokens xmlns:sp="https://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="https://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Always"/>
</wsp:Policy>
</sp:SignedSupportingTokens>

In addition you need to tell, which username should be included in the Usernametoken. This can be done using following assertion under RampartConfigs

<rampc:User>Alice</rampc:User>

Like the user name, we do not specify the password in the configuration file, instead we use a password callback mechanism, where we get a password for the above mentioned user name. The user has to specify a DLL or a module to load the password from. For this, following assertion is used.

<rampc:PasswordCallbackClass>/home/Alice/my_modules/pwcb.so</rampc:PasswordCallbackClass>

So what Rampart/C does is, first it loads the module dynamically and then call the function to get the password, which has to be implemented by the user. This gives user the flexibility to call databases, flat files or any other storage mechanism to extract the password.

The username token profile allows two ways to send a password. Either you can send the password in the plain text form or you can send as a digest of the password. This can be specified using following assertion.

<rampc:PasswordType>PlainText</rampc:PasswordType>

or

<rampc:PasswordType>Digest</rampc:PasswordType>

How to Encrypt

The encryption module in Rampart/C supports a wide variety of modes to encrypt a particular SOAP message. This gives a user more options but make it a little complex. So in the following discussion we are trying to explain only the essential parts of encryption related configurations, forwarding some examples.

  • Algorithm to be used:

    One decision that user has to take is, which algorithm to be used for the encryption. This is specified in the sp:AlgorithmSuite assertion as follows.

    <sp:AlgorithmSuite>
    <wsp:Policy>
    <sp:Basic256Rsa15/>
    </wsp:Policy>
    </sp:AlgorithmSuite>

    In the above example we have used the Basic256Rsa15 algorithm suite. By mapping this to the encryption process it actually uses the AES256 algorithm for the symmetric encryption, whilst using RSA-15 for the asymmetric encryption. The other possible values that can be used in Rampart/C are...
    Basic128Rsa15 : AES-128 (Sym) RSA-15 (Asym)
    Basic192Rsa15 : AES-192 (Sym) RSA-15 (Asym)
    TripleDesRsa15 : Tripple-DES (Sym) RSA-15 (Asym)
    Basic128 : AES-128 (Sym) RSA-15 (Asym)
    Basic192 : AES-192 (Sym) RSA-15 (Asym)
    Basic256 : AES-256 (Sym) RSA-15 (Asym)

  • Receiver's Certificate

    To encrypt a particular message user has to define an X509 certificate that contains the public key of the recipient. This is specified using the following assertion.

    <rampc:ReceiverCertificate>path/to/receiver's/certificate/cert.cert</rampc:ReceiverCertificate>

    This certificate contains the Receiver's public key, which actually is used to encrypt the session key.

  • Parts to be encrypted

    Currently Rampart/C encrypts SOAP message body and the signature header. To encrypt the body use

    <sp:EncryptedParts xmlns:sp="https://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
    <sp:Body/>
    </sp:EncryptedParts>

    To encrypt a signature header use

    <sp:EncryptSignature/>

How to Sign

To sign a SOAP message user has to define following items as policy assertions.

  1. Algorithm to be used:

    Please refer the Algorithm to be used section under How to Encrypt to see what values should be mentioned. All the algorithm suites that are supported right now, uses the RSA-SHA1 algorithm (https://www.w3.org/2000/09/xmldsig#rsa-sha1) for signing.

  2. Private Key and the certificate:

    User's private key is used to sign the message is specified as follows.

    <rampc:PrivateKey>/your/path/to/private/key/my_key.pem</rampc:PrivateKey>

    Also it's important to send the information about the certificate, which will be needed for the verification process.

    <rampc:Certificate>path/to/own/certificate/cert.cert</rampc:Certificate>
  3. Parts to be signed:

    Which parts to be signed in the SOAP message is determined by the sp:SignedParts assertion. User may specify to sign the body of the message and/or SOAP headers.

    <sp:SignedParts xmlns:sp="https://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
    <sp:Body/>
    <sp:Header Namespace="https://www.w3.org/2005/08/addressing"/>
    </sp:SignedParts>

    In the above example the user needs to sign the message body and all the addressing headers.
    Note that if timestamp is enabled, Rampart/C signs the Timestamp header element too.

How to Verify a Timestamp

In the recipient's policy, it's necessary to have the following assertion defined

<sp:IncludeTimestamp>

If the message doesn't contain a valid timestamp the recipient throws a SOAP fault.

How to Verify a Usernametoken

Similar to the insertion of Usernametoken here also we need to specify the sp:UsernameToken assertion under sp:SignedSupportingTokens.

<sp:SignedSupportingTokens xmlns:sp="https://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="https://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Always"/>
</wsp:Policy>
</sp:SignedSupportingTokens>

If the SOAP message doesn't contain a usernametoken, in the presence of the above, a SOAP fault will be thrown back. If contains, to validate the token we need to provide an application specific way. This can be done in two ways.

  1. Using a password callback mechanism (section: password callback module)
  2. Using an authentication module (section: authentication module)

How to Decrypt

Rampart/C gets data that are needed for the decryption process in two ways. That is, by scanning through the SOAP message and by reading the configurations. The policy configuration should provide followings.

  1. The private key

    The contents are encrypted by a public key, which usually included in a signed certificate. The recipients certificate is open to the public, whilst the private key is kept protected. The location of the private key is given by following assertion.

    <rampc:PrivateKey>/your/path/to/private/key.pem</rampc:PrivateKey>
  2. Which algorithm suite to be used.

    The recipient specifies the algorithm suite to be used by the following assertion.

    <sp:AlgorithmSuite>
    <wsp:Policy>
    <sp:Basic128Rsa15/>
    </wsp:Policy>
    </sp:AlgorithmSuite>

    In the above example it expects Basic128Rsa15 algorithm suite. i.e. In the context of encryption, it expects contents to be encrypted using the AES-128 algorithm. If a different algorithm suite is used, a SOAP fault is thrown back.

How to Verify a Signature

  1. The certificate to verify

    A signature over a SOAP message is verified by using the initiator's certificate. Usually this certificate or some information about it is sent by the initiator. For example it can be in the form of

    <wsse:BinarySecurityToken EncodingType="...">MIIDDDCCAfSg...==</wsse:BinarySecurityToken>

    If not directly in the message, Rampart/C tries to load the certificate from the system. So the user needs to specify it using following assertion.

    <rampc:ReceiverCertificate>/path/to/receivers/certificate.cert</rampc:ReceiverCertificate>
  2. The algorithm suite

    Similar to the encryption here also the algorithm suite is defined as follows

    <sp:AlgorithmSuite>
    <wsp:Policy>
    <sp:Basic128Rsa15/>
    </wsp:Policy>
    </sp:AlgorithmSuite>
  3. Which parts should be signed

    The recipient can enforce, which parts needs to be integrity protected in a SOAP message. If certain parts are not signed the recipient throws a SOAP fault back.

    <sp:SignedParts xmlns:sp="https://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
    <sp:Body/>
    <sp:Header Namespace="https://www.w3.org/2005/08/addressing"/>
    </sp:SignedParts>

How to Setup the Protection Order

Encrypt before signing and signing before the encryption are two basic requirements in computer security. So in SOAP messages too it's allowed to enable these. If the requirement is to Encrypt the content before signing the following assertion should be defined.

<sp:EncryptBeforeSigning/>

The default behavior is to sign the content before the encryption.

How to Enable Replay Detection

Rampart/C detects replays of SOAP messages and throws a SOAP fault back. By default this replay detection mechanism is turned OFF. To turn it ON, user has to add following assertion to the services's policy configurations.

<rampc:ReplayDetection>N</rampc:ReplayDetection>

The N here is the number of records that must be kept in memory. Greater the value of N is, greater the chance of detecting a replay.

How to Write a Password callback Module

The password callback module in Rampart/C, expects user to provide a password for a given user name. User has to implement a function and assign it in the following way.

rampart_callback_t* rcb = NULL;
/* Allocate memory*/
rcb = AXIS2_MALLOC(env->allocator,
sizeof(rampart_callback_t));
rcb->ops = AXIS2_MALLOC(
env->allocator, sizeof(rampart_callback_ops_t));
/*Assign function pointer*/
rcb->ops->callback_password = my_password_callback_function;

The above function can be used to call the databases, files or any other storage that is used to store the password. If the password is not found for the given user name, a NULL should be returned. Please refer the sample implementation under rampart/samples/callback for more details.

How to Write an Authentication Module

Similar to the password callback module, here also the user has to implement a function and assign it in the following way.

rampart_authn_provider_t* authn_p = NULL;

/*Allocate memory*/
authn_p = AXIS2_MALLOC(env->allocator,
sizeof(rampart_authn_provider_t));
authn_p->ops = AXIS2_MALLOC(
env->allocator, sizeof(rampart_authn_provider_ops_t));

/*Assign function pointers*/
authn_p->ops->rampart_authn_provider_check_password = my_sample_authn_provider_check_password;
authn_p->ops->rampart_authn_provider_check_password_digest = my_sample_authn_provider_check_password_digest;

The authentication module is different to the password callback module as it expects both the user name and the password. And the verification is expected to be done by the user. This gives user the flexibility to use his own ways of password digest mechanisms. If the username and password pair tally, the user should return the status RAMPART_AUTHN_PROVIDER_GRANTED. If not RAMPART_AUTHN_PROVIDER_DENIED should be returned.

Conclusion

Rampart/C configurations are based on policy assertions defined in the WS-Security Policy specifications 1.1. Apart from that Rampart/C defines it's own assertions too. By specifying all these assertions in the configurations files of Rampart/C, user can provide security to messages exchanged via the Axis2/C web services engine.

Namespace Usage

References

  1. Apache Rampart/C
  2. Rampart/C architecture guide
  3. Apache Axis2/C web services engine
  4. WS-Security Specification 1.0
  5. WS-Security Policy specifications 1.1

Author

Malinda Kaushalye Kapuruge is a Senior Software Engineer, WSO2 Inc. kaushalye at wso2 dot com

 

About Author

  • Malinda Kaushalye
  • Tech-lead
  • WSO2 Inc.