Rampart/C is deployed in Axis2/C engine as an axis2 module. Just as any other module you have to "engage" the Rampart/C with Axis2/C. All you have to do is to add following line to your descriptor file.
<module ref="rampart"/>
This allows Rampart/C to intercept messages exchanged via the engine and add/verify security claims. You may find several examples comes with Rampart/C under samples/secpolicy/. There are several identified scenarios that demonstrates Rampart/C features. This includes
In addition to that, if you want to provide Secure Token Service (STS) functionality to a service, add the following entry to your descriptor file.
<module ref="rahas"/>
Rampart/C configurations are based on WS Security Policy Language. Thus, we need to specify these policies in the descriptor file. For the client side we place them in a separate policy file, whilst in the server side we place them within either the services.xml or the axis2.xml.
For client side configurations, you need to create a client repository. This is the place where you keep axis2.xml, libraries and modules. When you create your service client, to invoke web services, you can give the client repository as follows.
svc_client = axis2_svc_client_create(env, "/my/path/to/client/repository");
In the axis2.xml, you need to engage Rampart/C as follows.
<module ref="rampart"/>
Then you may place your client's policy file in the client repository. Following is an example of a policy file.
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:ExactlyOne> <wsp:All> <sp:AsymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:InitiatorToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:InitiatorToken> <sp:RecipientToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never"> <wsp:Policy> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:RecipientToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256Rsa15/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Strict/> </wsp:Policy> </sp:Layout> </wsp:Policy> </sp:AsymmetricBinding> <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefEmbeddedToken/> <sp:MustSupportRefIssuerSerial/> </wsp:Policy> </sp:Wss10> <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <sp:Body/> </sp:SignedParts> <rampc:RampartConfig xmlns:rampc="http://ws.apache.org/rampart/c/policy"> <rampc:User>Bob</rampc:User> <rampc:EncryptionUser>b</rampc:EncryptionUser> <rampc:PasswordType>Digest</rampc:PasswordType> <rampc:PasswordCallbackClass>AXIS2C_HOME/samples/lib/rampartc/libpwcb.so</rampc:PasswordCallbackClass> <rampc:ReceiverCertificate>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/bob_cert.cert</rampc:ReceiverCertificate> <rampc:Certificate>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/alice_cert.cert</rampc:Certificate> <rampc:PrivateKey>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/alice_key.pem</rampc:PrivateKey> </rampc:RampartConfig> </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
In order to engage Rampart/C in the server side you need to add following line to your descriptor file. This can be either services.xml (service level) or axis2.xml (global level).
<module ref="rampart"/>
Then we place our policies within the descriptor file as follows.
<service name="sec_echo"> <parameter name="ServiceClass" locked="xsd:false">sec_echo</parameter> <description> This is a testing service , to test the system is working or not </description> <module ref="rampart"/> <operation name="echoString"> <parameter name="wsamapping">http://example.com/ws/2004/09/policy/Test/EchoRequest</parameter> </operation> <wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <!--Your policies are here--> </wsp:Policy> </service>
Here we will explain how to explore the various security features available in Rampart/C. We thoroughly recommend you to go through the samples available in Rampart/C in order see how these configurations are combined together.
To add a Timestamp to the SOAP message, user has to specify it in the policy by adding assertion
<sp:IncludeTimestamp/>
Beyond that user has to specify the duration of the validity of the message. This can be done by adding following Rampart/C specific assertion.
<rampc:TimeToLive>360</rampc:TimeToLive>
Here the time duration is specified using seconds. This would add a timestamp as follows to the security header. Note that the time difference is 360 seconds. If the message is not arrived within these limits, an error will be thrown back.
<wsu:Timestamp xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <wsu:Created>2007-06-18T05:10:01.448Z</wsu:Created> <wsu:Expires>2007-06-18T05:16:01.448Z</wsu:Expires> </wsu:Timestamp>
To add a username token to the SOAP message, user has to specify three things.
This can be done using following assertions in the policy file.
<rampc:RampartConfig xmlns:rampc="http://ws.apache.org/rampart/c/policy"> <rampc:User>Alice</rampc:User> <rampc:PasswordType>Digest</rampc:PasswordType> <rampc:PasswordCallbackClass>AXIS2C_HOME/samples/lib/rampartc/libpwcb.so</rampc:PasswordCallbackClass> </rampc:RampartConfig>
Also it's necessary to specify inclusion of username token in the policy as follows.
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Always"/>
Password callback modules: User passwords can be stored in different ways for different users. Passwords can be in databases, flat files... etc. Considering this Rampart/C provides an interface for users to write their own password callback modules. User has to assign the password callback function as follows.
rampart_callback_t* rcb = NULL; rcb = AXIS2_MALLOC(env->allocator, sizeof(rampart_callback_t)); rcb->ops = AXIS2_MALLOC(env->allocator, sizeof(rampart_callback_ops_t)); rcb->ops->callback_password = get_sample_password;/*Your password callback function*/
The signature of the password callback function is
axis2_char_t* AXIS2_CALL get_sample_password(rampart_callback_t *rcb, const axutil_env_t *env, const axis2_char_t *username, void param)
Please see the password callback sample available under samples/callback/pwcb.c for more details.
Specifying encryption options are a bit complex procedure. Thus here we wouldn't try to explain all WS Security Policy assertions. Following is a sample policy file that is used to encrypt SOAP messages.
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:ExactlyOne> <wsp:All> <sp:AsymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:InitiatorToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:InitiatorToken> <sp:RecipientToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never"> <wsp:Policy> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:RecipientToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256Rsa15/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Strict/> </wsp:Policy> </sp:Layout> </wsp:Policy> </sp:AsymmetricBinding> <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:MustSupportRefEmbeddedToken/> </wsp:Policy> </sp:Wss10> <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <sp:Body/> </sp:EncryptedParts> <rampc:RampartConfig xmlns:rampc="http://ws.apache.org/rampart/c/policy"> <rampc:User>Bob</rampc:User> <rampc:EncryptionUser>b</rampc:EncryptionUser> <rampc:PasswordCallbackClass>AXIS2C_HOME/samples/lib/rampartc/libpwcb.so</rampc:PasswordCallbackClass> <rampc:ReceiverCertificate>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/bob_cert.cert</rampc:ReceiverCertificate> <rampc:Certificate>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/alice_cert.cert</rampc:Certificate> <rampc:PrivateKey>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/alice_key.pem</rampc:PrivateKey> </rampc:RampartConfig> </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
In the above sample file we have specified the algorithm suite to be used for encryption. Here the algorithm suite is Basic256Rsa15.
<sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256Rsa15/> </wsp:Policy> </sp:AlgorithmSuite>
The parts to be encrypted are specified using following assertion. Here we have specified to encrypt the whole body.
<sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <sp:Body/> </sp:EncryptedParts>
The receiver's certificate is specified as follows. Here you have to specify the full path to the certificate. The public key of this certificate is used to encrypt the content.
<rampc:ReceiverCertificate>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/bob_cert.cert</rampc:ReceiverCertificate>
To decrypt an incoming message you have to specify your own private as follows. Here you have to specify the full path to the key.
<rampc:PrivateKey>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/alice_key.pem</rampc:PrivateKey>
Similar to the Encryption, to apply the signature we have to specify the signing parts, certificates and keys. Following is a sample policy file that is being used to sign a SOAP message.
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:ExactlyOne> <wsp:All> <sp:AsymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:InitiatorToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:InitiatorToken> <sp:RecipientToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never"> <wsp:Policy> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:RecipientToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256Rsa15/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Strict/> </wsp:Policy> </sp:Layout> </wsp:Policy> </sp:AsymmetricBinding> <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefEmbeddedToken/> <sp:MustSupportRefIssuerSerial/> </wsp:Policy> </sp:Wss10> <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <sp:Body/> </sp:SignedParts> <rampc:RampartConfig xmlns:rampc="http://ws.apache.org/rampart/c/policy"> <rampc:User>Bob</rampc:User> <rampc:EncryptionUser>b</rampc:EncryptionUser> <rampc:PasswordType>Digest</rampc:PasswordType> <rampc:PasswordCallbackClass>AXIS2C_HOME/samples/lib/rampartc/libpwcb.so</rampc:PasswordCallbackClass> <rampc:ReceiverCertificate>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/bob_cert.cert</rampc:ReceiverCertificate> <rampc:Certificate>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/alice_cert.cert</rampc:Certificate> <rampc:PrivateKey>AXIS2C_HOME/samples/src/rampartc/data/keys/ahome/alice_key.pem</rampc:PrivateKey> </rampc:RampartConfig> </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
To specify which parts of the message to be signed use following assertion. Here we have asked to sign the whole body.
<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <sp:Body/> </sp:SignedParts>
Optionally if you need to sign a header you may use.
<sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <sp:Header Namespace="http://www.w3.org/2005/08/addressing"/> </sp:SignedParts>
The algorithm suite to be used for signature is specified as follows. Same as encryption.
<sp:AlgorithmSuite> <wsp:Policy> <sp:Basic192Rsa15/> </wsp:Policy> </sp:AlgorithmSuite>
To detect replay attacks, Rampart/C has it's own Replay Detection module. This module detects if the message is a replay of a previous. By default the RD(Replay Detection) module is turned OFF. All you have to do turn it ON is to add
<rampc:ReplayDetection>N</rampc:ReplayDetection>
policy assertion to your descriptor file. Here N is the number of records that must be kept in memory. Greater the value of N is, greater the chance of detecting a replays. Rampart/C keeps records of messages in a list and process them on arrival of a new message. A record is the concatenation of message id(wsa:msg-id) and the value of the timestamp.
RECORD-ID = MSG-ID + TIMESTAMP
The message ID is considered to be unique to a particular message. But for this, user needs to have the addressing module engaged(which comes with axis2/c). This is NOT a MUST but is the RECOMONDED approach. One can just survive with only the timestamp. But shouldn't forget the chance of generating two message at the same time, which definitely make them suspicious as a replay.