|  | Home | Documentation | The gSOAP WS-Trust Extensible Framework updated by Robert van Engelen |

The gSOAP WS-Trust Extensible Framework

# The gSOAP WS-Trust Extensible Framework

The material in this section relates to the WS-Trust specification.

The WS-Trust framework is extensible. New client-side and server-side WS-Trust operations can be added. Several predefined operations are included to get you started. The list of predefined operations will be expanded over time. Please inquire Genivia tech support services.

To use the WS-Trust framework, make sure that the wst.h specification is imported in the .h file for soapcpp2, e.g. after running wsdl2h check the generated .h file:

#import "wst.h"
wst.h

If the import is not there, add it manually. Then run soapcpp2 as usual with option -Iimport to import wst.h from the import directory.

The wst.h and the WS-Trust-dependent wstx.h and other gSOAP-specific .h header files are located in the import directory of the gSOAP package. These files define the WS-Trust and other WS-* protocol header elements and types. The wstx.h header file defines the WS-Trust RequestSecurityTokenRequest and RequestSecurityTokenRequestCollection operations.

Compile your code with -DWITH_DOM and -DWITH_OPENSSL to enable WS-Security plugin API features.

Compile and link your code with wsseapi.c and wstapi.c, and include wsseapi.h and wstapi.h in your code.

Internally, the wstapi.c code enables SOAP 1.2 messaging. This will not affect your SOAP 1.1 messaging.

# WS-Trust Bindings

The WS-Trust bindings in wst.h in the import directory were generated from the WS-Trust schema for you with the wsdl2h tool and WS/WS-typemap.dat as follows:

    wsdl2h -cgyex -o wst.h -t WS/WS-typemap.dat WS/WS-Trust.xsd

The following modifications to wst.h are required to be made after generating wst.h with wsdl2h:

- Remove //gsoapopt
- Change http://docs.oasis-open.org/ws-sx/ws-trust/200512 to remove the trailing / (slash)
- Change //gsoap wst schema namespace directive to //gsoap wst schema import directive
- Add #import "wsp_appliesto.h"
- Add #import "wstx.h" at the end of the definitions in wst.h

# Expanding the Current WS-Trust Bindings

To expand or customize the WS-Trust bindings by adding (or removing) content model elements to the RequestSecurityToken and RequestSecurityTokenResponse, edit WS/WS-typemap.dat for the following two definition blocks:

    wst__RequestSecurityTokenType = $\
        _wsp__AppliesTo_*                    wsp__AppliesTo;
    wst__RequestSecurityTokenType = $\
        char*                                KeyType;
    wst__RequestSecurityTokenType = $\
        char*                                RequestType;
    wst__RequestSecurityTokenType = $\
        char*                                TokenType;
    wst__RequestSecurityTokenType = $\
        wst__EntropyType*                    Entropy;
    wst__RequestSecurityTokenType = $\
        char*                                ComputedKeyAlgorithm;
    wst__RequestSecurityTokenType = $\
        unsigned int*                        KeySize;
    wst__RequestSecurityTokenType = $\
        struct wst__BinaryExchangeType*      BinaryExchange;
    wst__RequestSecurityTokenType = $\
        struct wst__AuthenticatorType*       Authenticator;

    wst__RequestSecurityTokenResponseType = $\
        struct wst__RequestedSecurityTokenType* RequestedSecurityToken;
    wst__RequestSecurityTokenResponseType = $\
        struct wst__RequestedReferenceType*  RequestedAttachedReference;
    wst__RequestSecurityTokenResponseType = $\
        struct wst__RequestedReferenceType*  RequestedUnattachedReference;
    wst__RequestSecurityTokenResponseType = $\
        struct wst__RequestedProofTokenType* RequestedProofToken;
    wst__RequestSecurityTokenResponseType = $\
        struct wst__RequestedTokenCancelledType* RequestedTokenCancelled;
    wst__RequestSecurityTokenResponseType = $\
        char*                                KeyType;
    wst__RequestSecurityTokenResponseType = $\
        char*                                RequestType;
    wst__RequestSecurityTokenResponseType = $\
        char*                                TokenType;
    wst__RequestSecurityTokenResponseType = $\
        wst__EntropyType*                    Entropy;
    wst__RequestSecurityTokenResponseType = $\
        struct wst__BinaryExchangeType*      BinaryExchange;
    wst__RequestSecurityTokenResponseType = $\
        struct wst__AuthenticatorType*       Authenticator;

For example, to add the wst:Lifetime element to the RequestSecurityTokenResponse add the following two lines:

    wst__RequestSecurityTokenResponseType = $\
        wst__LifetimeType*                   Lifetime;

where wst__LifetimeType is declared in wst.h. The pointer makes it optional.

Then follow the instructions in the previous section to regenerate wst.h.

Given the new Lifetime element, the wstapi.c framework can be extended to use this element information as follows:

struct wst__RequestSecurityTokenResponseType response;
time_t expires = 0; // no expiration
...
if (soap_call___wst__RequestSecurityToken(soap, endpoint, soap_wst_rst_action, &request, &response))
{
soap_set_namespaces(soap, saved_namespaces);
return soap->error;
}
soap_set_namespaces(soap, saved_namespaces);
if (response.Lifetime && response.Lifetime->wsu__Expires)
soap_s2dateTime(soap, response.Lifetime->wsu__Expires, &expires); // set expiration
wst__RequestSecurityTokenResponseType
"http://docs.oasis-open.org/ws-sx/ws-trust/200512/":RequestSecurityTokenResponseType is a complexType...
Definition wst.h:313
soap_wst_rst_action
const char * soap_wst_rst_action
Definition wstapi.c:421
soap_call___wst__RequestSecurityToken
SOAP_FMAC5 int SOAP_FMAC6 soap_call___wst__RequestSecurityToken(struct soap *soap, const char *soap_endpoint, const char *soap_action, struct wst__RequestSecurityTokenType *wst__RequestSecurityToken, struct wst__RequestSecurityTokenResponseType *wst__RequestSecurityTokenResponse)

# Predefined WS-Trust Operations

This section lists the predefined WS-Trust operations implemented in wstapi.c.

## wst_soap_wst_request_saml_token

int soap_wst_request_saml_token(struct soap *soap, const char *endpoint, int soapver, const char *applyto, const char *username, const char *password, saml1__AssertionType **saml1, saml2__AssertionType **saml2)
saml1__AssertionType
"urn:oasis:names:tc:SAML:1.0:assertion":AssertionType is a complexType.
Definition saml1.h:173
saml2__AssertionType
"urn:oasis:names:tc:SAML:2.0:assertion":AssertionType is a complexType.
Definition saml2.h:220
soap_wst_request_saml_token
SOAP_FMAC1 int SOAP_FMAC2 soap_wst_request_saml_token(struct soap *soap, const char *endpoint, int soapver, const char *applyto, const char *username, const char *password, saml1__AssertionType **saml1, saml2__AssertionType **saml2)
Request SAML 1.0 or SAML 2.0 token. Verifies the SAML signature, which requires soap->cafile to be se...
Definition wstapi.c:494

Request SAML 1.0 or SAML 2.0 token, with endpoint service endpoint URL (send to), soapver SOAP version with 1 = SOAP 1.1, 2 = SOAP 1.2 (SOAP 1.2 is recommended), applyto is your service domain, username to authenticate or NULL, password to authenticate or NULL, saml1 if non-NULL, requests SAML 1.0 and upon return points to a pointer that is set to the SAML 1.0 assertion received, saml2 if non-NULL, requests SAML 2.0 and upon return points to a pointer that is set to the SAML 2.0 assertion received.

Returns SOAP_OK on success when the assertion could be verified, with saml1 or saml2 set.

For example:

#include "wstapi.h"
#include "wsaapi.h"
#include "wsseapi.h"
#include "wst.nsmap"
static int ssl_verify(int ok, X509_STORE_CTX *store) { return 1; } // ignore all cert warnings (bad)
...
struct soap *soap = soap_new1(SOAP_XML_INDENT);
int soapver = 2; // SOAP 1.2
const char *to = "https://yourcompany.com/adfs/services/trust/13/UsernameMixed";
const char *applyto = "yourcompany.com";
const char *username = "yourusername";
const char *password = "yourpassword";
saml2__AssertionType *saml2;
// register wsa plugin (optional, only if the client requires WS-Addressing rerouted messaging)
soap_register_plugin(soap, soap_wsa);
// register wsse plugin
soap_register_plugin(soap, soap_wsse);
// HTTPS settings
if (soap_ssl_client_context(soap, SOAP_SSL_DEFAULT, NULL, NULL, "cacerts.pem", NULL, NULL))
{
soap_print_fault(soap, stderr);
exit(1);
}
// HTTPS and SAML certificate verification callback
soap->fsslverify = ssl_verify;
// SAML 2.0 token request
if (soap_wst_request_saml_token(soap, to, soapver, applyto, username, password, NULL, &saml2))
{
soap_print_fault(soap, stderr);
}
else
{
// display subset of the assertion information
if (saml2)
{
int i;
for (i = 0; i < saml2->__size_AssertionType; i++)
{
if (saml2->__union_AssertionType[i].saml2__Statement)
{
// omitted from displaying
}
if (saml2->__union_AssertionType[i].saml2__AuthnStatement)
{
if (saml2->__union_AssertionType[i].saml2__AuthnStatement->saml2__AuthnContext)
{
if (saml2->__union_AssertionType[i].saml2__AuthnStatement->saml2__AuthnContext->saml2__AuthnContextClassRef)
printf("AuthnStatement Context: %s\n", saml2->__union_AssertionType[i].saml2__AuthnStatement->saml2__AuthnContext->saml2__AuthnContextClassRef);
}
}
if (saml2->__union_AssertionType[i].saml2__AuthzDecisionStatement)
{
// omitted from displaying
}
if (saml2->__union_AssertionType[i].saml2__AttributeStatement)
{
int j;
for (j = 0; j < saml2->__union_AssertionType[i].saml2__AttributeStatement->__size_AttributeStatementType; j++)
{
if (saml2->__union_AssertionType[i].saml2__AttributeStatement->__union_AttributeStatementType[j].saml2__Attribute)
{
int k;
for (k = 0; k < saml2->__union_AssertionType[i].saml2__AttributeStatement->__union_AttributeStatementType[j].saml2__Attribute->__sizeAttributeValue; k++)
printf("Type: %s\nValue: %s\n", saml2->__union_AssertionType[i].saml2__AttributeStatement->__union_AttributeStatementType[j].saml2__Attribute->Name, saml2->__union_AssertionType[i].saml2__AttributeStatement->__union_AttributeStatementType[j].saml2__Attribute->saml2__AttributeValue[k]);
}
}
}
}
if (saml2->saml2__Conditions)
{
if (saml2->saml2__Conditions->NotBefore)
printf("Not before %s\n", soap_dateTime2s(soap, *saml2->saml2__Conditions->NotBefore));
if (saml2->saml2__Conditions->NotOnOrAfter)
printf("Not on or after %s\n", soap_dateTime2s(soap, *saml2->saml2__Conditions->NotOnOrAfter));
}
}
else
{
printf("No SAML 2.0 statements!\n");
}
}
soap_destroy(soap);
soap_end(soap);
soap_free(soap);
saml2__AssertionType::__saml2__union_AssertionType::saml2__AuthnStatement
struct saml2__AuthnStatementType * saml2__AuthnStatement
Element reference "urn:oasis:names:tc:SAML:2.0:assertion:"AuthnStatement.
Definition saml2.h:238
saml2__AssertionType::__saml2__union_AssertionType::saml2__AttributeStatement
struct saml2__AttributeStatementType * saml2__AttributeStatement
Element reference "urn:oasis:names:tc:SAML:2.0:assertion:"AttributeStatement.
Definition saml2.h:242
saml2__AssertionType::__saml2__union_AssertionType::saml2__Statement
struct saml2__StatementAbstractType * saml2__Statement
Element reference "urn:oasis:names:tc:SAML:2.0:assertion:"Statement.
Definition saml2.h:236
saml2__AssertionType::__saml2__union_AssertionType::saml2__AuthzDecisionStatement
struct saml2__AuthzDecisionStatementType * saml2__AuthzDecisionStatement
Element reference "urn:oasis:names:tc:SAML:2.0:assertion:"AuthzDecisionStatement.
Definition saml2.h:240
saml2__AssertionType::__union_AssertionType
struct saml2__AssertionType::__saml2__union_AssertionType * __union_AssertionType
saml2__AssertionType::__size_AssertionType
$ int __size_AssertionType
Definition saml2.h:232
saml2__AssertionType::saml2__Conditions
struct saml2__ConditionsType * saml2__Conditions
Element reference "urn:oasis:names:tc:SAML:2.0:assertion:"Conditions.
Definition saml2.h:228
saml2__AttributeStatementType::__saml2__union_AttributeStatementType::saml2__Attribute
struct saml2__AttributeType * saml2__Attribute
Element reference "urn:oasis:names:tc:SAML:2.0:assertion:"Attribute.
Definition saml2.h:731
saml2__AttributeStatementType::__union_AttributeStatementType
struct saml2__AttributeStatementType::__saml2__union_AttributeStatementType * __union_AttributeStatementType
saml2__AttributeStatementType::__size_AttributeStatementType
$ int __size_AttributeStatementType
INHERITED FROM saml2__StatementAbstractType:
Definition saml2.h:727
saml2__AttributeType::saml2__AttributeValue
_XML * saml2__AttributeValue
Array _XML* of size 0..unbounded.
Definition saml2.h:506
saml2__AttributeType::__sizeAttributeValue
$ int __sizeAttributeValue
Size of the dynamic array of values of type _XML* is 0..unbounded.
Definition saml2.h:504
saml2__AttributeType::Name
char * Name
Attribute "Name" of type xs:string.
Definition saml2.h:508
saml2__AuthnContextType::saml2__AuthnContextClassRef
char * saml2__AuthnContextClassRef
Element reference "urn:oasis:names:tc:SAML:2.0:assertion:"AuthnContextClassRef.
Definition saml2.h:444
saml2__AuthnStatementType::saml2__AuthnContext
struct saml2__AuthnContextType * saml2__AuthnContext
Element reference "urn:oasis:names:tc:SAML:2.0:assertion:"AuthnContext.
Definition saml2.h:660
saml2__ConditionsType::NotBefore
xsd__dateTime * NotBefore
Attribute "NotBefore" of type xs:dateTime.
Definition saml2.h:339
saml2__ConditionsType::NotOnOrAfter
xsd__dateTime * NotOnOrAfter
Attribute "NotOnOrAfter" of type xs:dateTime.
Definition saml2.h:341
wstapi.h

This prints several of the assertion's properties, including the conditions under which the assertion is valid. The NotBefore and NotOnOrAfter conditions can be checked against the current time as follows:

time_t now = time(NULL);
if (saml2->saml2__Conditions->NotBefore && *saml2->saml2__Conditions->NotBefore > now)
... error // not valid yet
if (saml2->saml2__Conditions->NotOnOrAfter && *saml2->saml2__Conditions->NotOnOrAfter <= now)
... error // expired

## wst_soap_wst_request_psha1_token

int soap_wst_request_psha1_token(struct soap *soap, const char *endpoint, int soapver, const char *applyto, const char *username, const char *password, char *psha1, size_t psha1len)
soap_wst_request_psha1_token
SOAP_FMAC1 int SOAP_FMAC2 soap_wst_request_psha1_token(struct soap *soap, const char *endpoint, int soapver, const char *applyto, const char *username, const char *password, char *psha1, size_t psha1len)
Request PSHA1 token.
Definition wstapi.c:581

Request P_SHA1 token with endpoint service endpoint URL (send to), soapver SOAP version with 1 = SOAP 1.1, 2 = SOAP 1.2 (SOAP 1.2 is recommended), applyto your service domain, username to authenticate or NULL, password to authenticate or NULL, psha1 is filled with the P_SHA1 result token of psa1len bytes.

Returns SOAP_OK on success.

#include "wsaapi.h"
#include "wstapi.h"
#include "wsseapi.h"
#include "wst.nsmap"
static int ssl_verify(int ok, X509_STORE_CTX *store) { return 1; } // ignore all cert warnings (bad)
...
struct soap *soap = soap_new1(SOAP_XML_INDENT);
int soapver = 2; // SOAP 1.2
const char *to = "https://yourcompany.com/adfs/services/trust/13/UsernameMixed";
const char *applyto = "yourcompany.com";
const char *username = "yourusername";
const char *password = "yourpassword";
char psha1[256];
// register wsa plugin (optional, only if the client requires WS-Addressing rerouted messaging)
soap_register_plugin(soap, soap_wsa);
// register wsse plugin
soap_register_plugin(soap, soap_wsse);
// HTTPS settings
if (soap_ssl_client_context(soap, SOAP_SSL_DEFAULT, NULL, NULL, "cacerts.pem", NULL, NULL))
{
soap_print_fault(soap, stderr);
exit(1);
}
// HTTPS certificate verification callback
soap->fsslverify = ssl_verify;
// PSHA1 token request
if (soap_wst_request_psha1_token(soap, to, soapver, applyto, username, password, psha1, 256))
{
soap_print_fault(soap, stderr);
}
else
{
// use psha1[0..255]
}
soap_destroy(soap);
soap_end(soap);
soap_free(soap);

## wst_soap_wst_request_psha256_token

Similar to the previous section, request a P_SHA256 token with:

int soap_wst_request_psha256_token(struct soap *soap, const char *endpoint, int soapver, const char *applyto, const char *username, const char *password, char *psha256, size_t psha256len)

# Using the wst Plugin for Servers

To implement a WS-Trust server in C, run soapcpp2 as follows:

    soapcpp2 -c -L file.h

where file.h has an #import "wst.h". This generates the soapServer.c and soapC.c code you need to compile with wstapi.c, wsaapi.c, wsseapi.c, smdevp.c, and mecevp.c. Link with libgsoapssl.a (or stdsoap2.c and dom.c). Use -DWITH_OPENSSL and -DWITH_DOM to compile the source code.

For C++, use:

    soapcpp2 -L file.h

This generates the soapServer.cpp and soapC.cpp code you need to compile with wstapi.c, wsaapi.c, wsseapi.c, smdevp.c, and mecevp.c. Link with libgsoapssl++.a (or stdsoap2.cpp and dom.cpp). Use -DWITH_OPENSSL and -DWITH_DOM to compile the source code.

If you prefer to use soapcpp2 option -j (or -i) to generate C++ server objects, please run soacpp2 again as follows:

    soapcpp2 -j -L file.h
    soapcpp2 -CL -pwst import/wst.h

This generates wstClient.cpp, which should be compiled together with the rest of your project code.

You should define the following service operations:

int wstService::RequestSecurityToken(wst__RequestSecurityTokenType *request, wst__RequestSecurityTokenResponseType *response)
{
...
}
int wstService::RequestSecurityTokenCollection(struct wst__RequestSecurityTokenCollectionType *request, struct wst__RequestSecurityTokenResponseCollectionType *response)
{
...
}
wst__RequestSecurityTokenCollectionType
"http://docs.oasis-open.org/ws-sx/ws-trust/200512/":RequestSecurityTokenCollectionType is a complexTy...
Definition wst.h:411
wst__RequestSecurityTokenResponseCollectionType
"http://docs.oasis-open.org/ws-sx/ws-trust/200512/":RequestSecurityTokenResponseCollectionType is a c...
Definition wst.h:431
wst__RequestSecurityTokenType
Imported simpleType "http://docs.oasis-open.org/ws-sx/ws-trust/200512/":RequestTypeOpenEnum from type...
Definition wst.h:232

If you are combinding WS-Trust with other service operations, then you must also chain the service operations at the server side as follows:

if (soap_begin_serve(service.soap) == SOAP_OK)
if (service.dispatch() == SOAP_NO_METHOD)
soap_serve_request(service.soap);

where the service object is an instance of the application services generated by soapcpp2 -j.