497 lines
16 KiB
C
497 lines
16 KiB
C
/* $Id: wsf_profile.c,v 1.45 2007/01/05 16:11:02 Exp $
|
|
*
|
|
* Lasso - A free implementation of the Liberty Alliance specifications.
|
|
*
|
|
* Copyright (C) 2004-2007 Entr'ouvert
|
|
* http://lasso.entrouvert.org
|
|
*
|
|
* Authors: See AUTHORS file in top-level directory.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "soap_binding.h"
|
|
#include "../xml/idwsf_strings.h"
|
|
#include "../xml/id-wsf-2.0/idwsf2_strings.h"
|
|
#include "../xml/id-wsf-2.0/sb2_sender.h"
|
|
#include "../xml/id-wsf-2.0/sb2_redirect_request.h"
|
|
#include "../xml/id-wsf-2.0/sb2_user_interaction_header.h"
|
|
#include "../xml/ws/wsa_attributed_uri.h"
|
|
|
|
#include "../utils.h"
|
|
|
|
#define get_header(test) \
|
|
GList *i = NULL; \
|
|
\
|
|
if (! LASSO_IS_SOAP_ENVELOPE(soap_envelope)) \
|
|
return NULL; \
|
|
if (! LASSO_IS_SOAP_HEADER(soap_envelope->Header)) \
|
|
return NULL; \
|
|
\
|
|
i = soap_envelope->Header->Other; \
|
|
for (; i != NULL; i = g_list_next(i)) { \
|
|
if (test(i->data)) { \
|
|
break; \
|
|
} \
|
|
}
|
|
|
|
inline static LassoNode* _get_node(GList **list, GType node_type, const char *node_name,
|
|
const char *node_namespace, const char *node_prefix, gboolean create);
|
|
|
|
/**
|
|
* lasso_soap_envelope_sb2_get_provider_id:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
*
|
|
* Return the providerID contained in the sb2:Sender header.
|
|
*
|
|
* Return value: the providerID string or NULL if no sb2:Sender header is present.
|
|
*/
|
|
char *
|
|
lasso_soap_envelope_sb2_get_provider_id(LassoSoapEnvelope *soap_envelope)
|
|
{
|
|
get_header(LASSO_IS_IDWSF2_SB2_SENDER);
|
|
|
|
if (i)
|
|
return g_strdup(((LassoIdWsf2Sb2Sender*)i->data)->providerID);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_sb2_get_redirect_request_url:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
*
|
|
* <para>Return the redirect request URL from the sb2:RedirectRequest SOAP Fault detail.</para>
|
|
*
|
|
* <para>The WSC MUST verify that this URL belong to the WSP. You can do this by comparing the domain
|
|
* with the one in the @LassoProfile.msg_url field</para>
|
|
* <para>The WSC MUST redirect the User Agent to this URL with a GET or POST request. It MUST add a
|
|
* parameter named ReturnToURL giving the URL where the WSP will send the User Agent after the
|
|
* interaction. It MAY add an IDP parameter indicating to the WSP how to authenticate the principal
|
|
* if no preexisting session with the User Agent exists</para>
|
|
*<para>The WSP must check that the ReturnToURL belon to the WSP, by using the providerID URL for example.</para>
|
|
<para>After the interaction the WSC must redirect the User Agent to the ReturnToURL URL adding a parameter named ResendMessage. If ResendMessage is 0 or false, it means that the principal refused to continue the process. Any other value means that the prinicpal accepted and so the WSC can try again its request.</para>
|
|
<para>In order to succeed the request need to refer to the SOAP Fault response containing the RedirectRequest element. See lasso_soap_envelope_get_relates_to(), and #LassoWsAddrAttributedURI.</para>
|
|
*
|
|
* Return value:(transfer none)(allow-none): the redirect URL string or NULL if no sb2:RedirectRequest detail is present.
|
|
*/
|
|
const char *
|
|
lasso_soap_envelope_sb2_get_redirect_request_url(LassoSoapEnvelope *soap_envelope)
|
|
{
|
|
LassoSoapFault *fault;
|
|
LassoIdWsf2Sb2RedirectRequest *redirect_request;
|
|
|
|
fault = lasso_soap_envelope_get_soap_fault(soap_envelope, FALSE);
|
|
if (! fault || ! LASSO_IS_SOAP_DETAIL(fault->Detail))
|
|
return NULL;
|
|
|
|
redirect_request = (LassoIdWsf2Sb2RedirectRequest*) _get_node(&fault->Detail->any, LASSO_TYPE_IDWSF2_SB2_REDIRECT_REQUEST, NULL, NULL, NULL, FALSE);
|
|
if (! redirect_request)
|
|
return NULL;
|
|
return redirect_request->redirectURL;
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_sb2_get_target_identity_header:
|
|
* @soap_envelope: a #LassoSoapEnvelope object.
|
|
*
|
|
* Return the first sb2:TargetIdentity header.
|
|
*
|
|
* Return value: (transfer none): the first #LassoIdWsf2Sb2TargetIdentity object found in the
|
|
* headers of the @soap_envelope, or NULL if none is found.
|
|
*/
|
|
LassoIdWsf2Sb2TargetIdentity*
|
|
lasso_soap_envelope_sb2_get_target_identity_header(LassoSoapEnvelope *soap_envelope)
|
|
{
|
|
get_header(LASSO_IS_IDWSF2_SB2_TARGET_IDENTITY);
|
|
|
|
if (i)
|
|
return (LassoIdWsf2Sb2TargetIdentity*)i->data;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* lasso_soap_envelope_wssec_get_security_header_impl:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
* @create: wether to create the header if not found
|
|
*
|
|
* Return value: (transfer none): the wsse:Security header found in the SOAP message, or NULL if
|
|
* none is found, and creation was not allowed.
|
|
*/
|
|
static LassoWsSec1SecurityHeader*
|
|
lasso_soap_envelope_wssec_get_security_header_impl(LassoSoapEnvelope *soap_envelope,
|
|
gboolean create)
|
|
{
|
|
get_header(LASSO_IS_WSSE_SECURITY_HEADER);
|
|
|
|
if (i) {
|
|
return (LassoWsSec1SecurityHeader*)i->data;
|
|
}
|
|
|
|
if (create) {
|
|
LassoWsSec1SecurityHeader *wssec_security = lasso_wsse_security_header_new();
|
|
lasso_list_add_new_gobject (soap_envelope->Header->Other, wssec_security);
|
|
return wssec_security;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_wssec_get_security_header:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
*
|
|
* Return the first wsse:Security header found in the headers of @soap_envelope.
|
|
*
|
|
* Return value: (transfer none): the wsse:Security header found in the SOAP message, or NULL if
|
|
* none is found.
|
|
*/
|
|
LassoWsSec1SecurityHeader*
|
|
lasso_soap_envelope_wssec_get_security_header(LassoSoapEnvelope *soap_envelope)
|
|
{
|
|
return lasso_soap_envelope_wssec_get_security_header_impl (soap_envelope, FALSE);
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_add_security_token:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
* @token: a #LassoNode to use as a security token
|
|
*
|
|
* Add @token as a security token to the headers of @soap_envelope using a
|
|
* #LassoWsSec1SecurityHeader element as a container. Eventually create the
|
|
* #LassoWsSec1SecurityHeader element if it does not exist already.
|
|
*/
|
|
void
|
|
lasso_soap_envelope_add_security_token(LassoSoapEnvelope *soap_envelope, LassoNode *token)
|
|
{
|
|
LassoWsSec1SecurityHeader *wssec_security;
|
|
|
|
wssec_security = lasso_soap_envelope_wssec_get_security_header_impl (soap_envelope, TRUE);
|
|
g_return_if_fail (wssec_security != NULL);
|
|
lasso_list_add_gobject(wssec_security->any, token);
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_get_saml2_security_token:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
*
|
|
* Return a SAML2 Assertion used as a security token if one is found in the headers of
|
|
* @soap_envelope.
|
|
*
|
|
* Return value: (transfer none): a #LassoSaml2Assertion, or NULL if none is found.
|
|
*/
|
|
LassoSaml2Assertion*
|
|
lasso_soap_envelope_get_saml2_security_token(LassoSoapEnvelope *soap_envelope)
|
|
{
|
|
const LassoWsSec1SecurityHeader *security;
|
|
GList *it;
|
|
|
|
security = lasso_soap_envelope_wssec_get_security_header (soap_envelope);
|
|
if (! security)
|
|
return NULL;
|
|
lasso_foreach (it, security->any) {
|
|
if (LASSO_IS_SAML2_ASSERTION (it->data)) {
|
|
return (LassoSaml2Assertion*)g_object_ref(it->data);
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_add_action_header:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
* @action: the action targeted by this message
|
|
*
|
|
* Add an action header to a #LassoSoapEnvelope object.
|
|
*/
|
|
void
|
|
lasso_soap_envelope_add_action(LassoSoapEnvelope *soap_envelope, const char *action)
|
|
{
|
|
LassoWsAddrAttributedURI *wsa_action;
|
|
|
|
if (! LASSO_IS_SOAP_ENVELOPE(soap_envelope) || ! LASSO_IS_SOAP_HEADER(soap_envelope->Header))
|
|
return;
|
|
wsa_action = lasso_wsa_attributed_uri_new_with_string(action);
|
|
lasso_node_set_custom_nodename(&wsa_action->parent, "Action");
|
|
lasso_list_add_new_gobject(soap_envelope->Header->Other, wsa_action);
|
|
}
|
|
|
|
const char*
|
|
lasso_soap_envelope_get_action(LassoSoapEnvelope *soap_envelope)
|
|
{
|
|
GList *i;
|
|
|
|
if (! LASSO_IS_SOAP_ENVELOPE(soap_envelope) || ! LASSO_IS_SOAP_HEADER(soap_envelope->Header))
|
|
return NULL;
|
|
|
|
lasso_foreach(i, soap_envelope->Header->Other) {
|
|
if (LASSO_IS_WSA_ATTRIBUTED_URI(i->data)
|
|
&& lasso_strisequal(lasso_node_get_name((LassoNode *)i->data),"Action")) {
|
|
return ((LassoWsAddrAttributedURI*)i->data)->content;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_add_to_body:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
* @content: a #LassoNode object to add to the body of the SOAP message
|
|
*
|
|
* Add new content to the SOAP message body.
|
|
*/
|
|
void
|
|
lasso_soap_envelope_add_to_body(LassoSoapEnvelope *soap_envelope, LassoNode *content)
|
|
{
|
|
if (!LASSO_IS_SOAP_ENVELOPE(soap_envelope) || !LASSO_IS_SOAP_BODY(soap_envelope->Body))
|
|
return;
|
|
lasso_list_add_gobject(soap_envelope->Body->any, content);
|
|
}
|
|
|
|
inline static LassoNode*
|
|
_get_node(GList **list, GType node_type, const char *node_name, const char *node_namespace,
|
|
const char *node_prefix, gboolean create)
|
|
{
|
|
GList *i;
|
|
|
|
lasso_foreach(i, (*list)) {
|
|
LassoNode *node = (LassoNode*)i->data;
|
|
|
|
if (LASSO_IS_NODE(node) &&
|
|
(! node_type || ( G_IS_OBJECT(node) && G_OBJECT_TYPE(node) == node_type)) &&
|
|
(! node_name || lasso_strisequal(lasso_node_get_name(node),node_name)) &&
|
|
(! node_namespace ||
|
|
lasso_strisequal(lasso_node_get_namespace(node),node_namespace))) {
|
|
return node;
|
|
}
|
|
}
|
|
if (create) {
|
|
LassoNode *node = (LassoNode*)g_object_new(node_type, NULL);
|
|
if (! node) {
|
|
return NULL;
|
|
}
|
|
if (lasso_strisnotequal(lasso_node_get_name(node),node_name)) {
|
|
lasso_node_set_custom_nodename(node, node_name);
|
|
}
|
|
if (lasso_strisequal(lasso_node_get_namespace(node),node_namespace)) {
|
|
lasso_node_set_custom_namespace(node, node_namespace, node_prefix);
|
|
}
|
|
lasso_list_add_new_gobject(*list, node);
|
|
return node;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
LassoNode*
|
|
_lasso_soap_envelope_get_header(LassoSoapEnvelope *soap_envelope, GType node_type,
|
|
const char *node_name, const char *node_namespace, const char *node_prefix,
|
|
gboolean create)
|
|
{
|
|
if (! LASSO_IS_SOAP_ENVELOPE(soap_envelope) || !
|
|
LASSO_IS_SOAP_HEADER(soap_envelope->Header)) {
|
|
return NULL;
|
|
}
|
|
|
|
return _get_node(&soap_envelope->Header->Other, node_type, node_name, node_namespace,
|
|
node_prefix, create);
|
|
}
|
|
|
|
|
|
/**
|
|
* lasso_soap_envelope_get_message_id:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
* @create:(default FALSE): whether to create the node if it is not found
|
|
*
|
|
* Return the WS-Addressing header MessageID content.
|
|
*
|
|
* Return value:(transfer none): a #LassoWsAddrAttributedURI object or NULL if none is found, and
|
|
* creation was not allowed.
|
|
*/
|
|
LassoWsAddrAttributedURI*
|
|
lasso_soap_envelope_get_message_id(LassoSoapEnvelope *soap_envelope, gboolean create)
|
|
{
|
|
return (LassoWsAddrAttributedURI*)_lasso_soap_envelope_get_header(soap_envelope,
|
|
LASSO_TYPE_WSA_ATTRIBUTED_URI, LASSO_WSA_ELEMENT_MESSAGE_ID, NULL, NULL,
|
|
create);
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_get_relates_to:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
* @create:(default FALSE): whether to create the node if it is not found
|
|
*
|
|
*
|
|
* Returns the RelatesTo WS-Addressing header, if it exists.
|
|
*
|
|
* Return value:(transfer none): a #LassoWsAddrAttributedURI object or NULL if none is found, and creation was not allowed.
|
|
*/
|
|
LassoWsAddrRelatesTo*
|
|
lasso_soap_envelope_get_relates_to(LassoSoapEnvelope *soap_envelope, gboolean create)
|
|
{
|
|
return (LassoWsAddrRelatesTo*)_lasso_soap_envelope_get_header(soap_envelope,
|
|
LASSO_TYPE_WSA_RELATES_TO, NULL, NULL, NULL, create);
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_set_relates_to:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
* @value:(allow-none): the value to set into the new header
|
|
* @relationship:(allow-none): kind of the relationship
|
|
*
|
|
* Set the value of the RelatesTo header, if it does not exist it is created. If @value is NULL, the
|
|
* header is removed.
|
|
*/
|
|
void
|
|
lasso_soap_envelope_set_relates_to(LassoSoapEnvelope *soap_envelope, char *value, char *relationship)
|
|
{
|
|
LassoWsAddrRelatesTo *relates_to;
|
|
if (! LASSO_IS_SOAP_ENVELOPE(soap_envelope))
|
|
return;
|
|
|
|
|
|
relates_to = lasso_soap_envelope_get_relates_to(soap_envelope, TRUE);
|
|
if (value) {
|
|
g_return_if_fail(relates_to);
|
|
lasso_assign_string(relates_to->content, value);
|
|
lasso_assign_string(relates_to->RelationshipType, relationship);
|
|
} else if (relates_to) {
|
|
lasso_list_remove_gobject(soap_envelope->Header->Other, relates_to);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_get_body_content:
|
|
* @soap_envelope: a #LassoSoapEnvelope object
|
|
*
|
|
* Return the body content of the @soap_envelope object.
|
|
*
|
|
* Return value:(element-type LassoNode): the content or NULL if the concent is empty or the object invalid.
|
|
*/
|
|
GList*
|
|
lasso_soap_envelope_get_body_content(LassoSoapEnvelope *soap_envelope) {
|
|
if (LASSO_IS_SOAP_ENVELOPE(soap_envelope) && LASSO_IS_SOAP_BODY(soap_envelope->Body))
|
|
return soap_envelope->Body->any;
|
|
return NULL;
|
|
}
|
|
|
|
LassoSoapDetail *
|
|
lasso_soap_fault_get_detail(LassoSoapFault *soap_fault, gboolean create)
|
|
{
|
|
if (! LASSO_IS_SOAP_FAULT(soap_fault))
|
|
return NULL;
|
|
|
|
if (soap_fault->Detail == NULL && create) {
|
|
soap_fault->Detail = lasso_soap_detail_new();
|
|
}
|
|
return soap_fault->Detail;
|
|
}
|
|
|
|
|
|
/**
|
|
* lasso_soap_fault_add_to_detail:
|
|
* @soap_fault: a #LassoSoapFault object
|
|
* @node: a node to add to the Detail sub-element of the @soap_fault object.
|
|
*
|
|
* Fill the detail part of a SOAP fault.
|
|
*/
|
|
void
|
|
lasso_soap_fault_add_to_detail(LassoSoapFault *soap_fault,
|
|
LassoNode *node)
|
|
{
|
|
LassoSoapDetail *detail;
|
|
|
|
detail = lasso_soap_fault_get_detail(soap_fault, TRUE);
|
|
if (detail) {
|
|
lasso_list_add_gobject(detail->any, node);
|
|
}
|
|
}
|
|
|
|
LassoIdWsf2Sb2UserInteractionHeader *
|
|
lasso_soap_envelope_get_sb2_user_interaction_header(LassoSoapEnvelope *soap_envelope, gboolean create)
|
|
{
|
|
return (LassoIdWsf2Sb2UserInteractionHeader*)_lasso_soap_envelope_get_header(soap_envelope,
|
|
LASSO_TYPE_IDWSF2_SB2_USER_INTERACTION_HEADER, NULL, NULL, NULL,
|
|
create);
|
|
}
|
|
|
|
LassoIdWsf2Sb2UserInteractionHint
|
|
lasso_soap_envelope_get_sb2_user_interaction_hint(LassoSoapEnvelope *soap_envelope)
|
|
{
|
|
const char *hint;
|
|
LassoIdWsf2Sb2UserInteractionHeader *header;
|
|
|
|
header = lasso_soap_envelope_get_sb2_user_interaction_header(soap_envelope, FALSE);
|
|
if (header) {
|
|
hint = header->interact;
|
|
if (lasso_strisequal(hint,LASSO_SB2_USER_INTERACTION_INTERACT_IF_NEEDED))
|
|
return LASSO_IDWSF2_SB2_USER_INTERACTION_HINT_INTERACT_IF_NEEDED;
|
|
if (lasso_strisequal(hint,LASSO_SB2_USER_INTERACTION_DO_NOT_INTERACT))
|
|
return LASSO_IDWSF2_SB2_USER_INTERACTION_HINT_DO_NOT_INTERACT;
|
|
if (lasso_strisequal(hint,LASSO_SB2_USER_INTERACTION_DO_NOT_INTERACT_FOR_DATA))
|
|
return LASSO_IDWSF2_SB2_USER_INTERACTION_HINT_DO_NOT_INTERACT_FOR_DATA;
|
|
|
|
}
|
|
return LASSO_IDWSF2_SB2_USER_INTERACTION_HINT_NONE;
|
|
}
|
|
|
|
void
|
|
lasso_soap_envelope_set_sb2_user_interaction_hint(LassoSoapEnvelope *soap_envelope,
|
|
LassoIdWsf2Sb2UserInteractionHint hint)
|
|
{
|
|
LassoIdWsf2Sb2UserInteractionHeader *user_interaction;
|
|
|
|
user_interaction = lasso_soap_envelope_get_sb2_user_interaction_header(soap_envelope, TRUE);
|
|
switch (hint) {
|
|
case LASSO_IDWSF2_SB2_USER_INTERACTION_HINT_INTERACT_IF_NEEDED:
|
|
lasso_assign_string(user_interaction->interact,
|
|
LASSO_SB2_USER_INTERACTION_INTERACT_IF_NEEDED);
|
|
break;
|
|
case LASSO_IDWSF2_SB2_USER_INTERACTION_HINT_DO_NOT_INTERACT:
|
|
lasso_assign_string(user_interaction->interact,
|
|
LASSO_SB2_USER_INTERACTION_DO_NOT_INTERACT);
|
|
break;
|
|
case LASSO_IDWSF2_SB2_USER_INTERACTION_HINT_DO_NOT_INTERACT_FOR_DATA:
|
|
lasso_assign_string(user_interaction->interact,
|
|
LASSO_SB2_USER_INTERACTION_DO_NOT_INTERACT_FOR_DATA);
|
|
break;
|
|
default:
|
|
lasso_release_string(user_interaction->interact);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* lasso_soap_envelope_get_soap_fault:
|
|
* @soap_envelope: a #LassoSoapEnvelope
|
|
* @create:(default FALSE): whether to create the SOAP Fault
|
|
*
|
|
* Return the first SOAP Fault in the Body of the soap message @soap_envelope.
|
|
*
|
|
* Return value:(transfer none)(allow-none): a #LassoSoapFault object or NULL.
|
|
*/
|
|
LassoSoapFault*
|
|
lasso_soap_envelope_get_soap_fault(LassoSoapEnvelope *soap_envelope, gboolean create)
|
|
{
|
|
LassoSoapFault *fault;
|
|
|
|
if (! LASSO_IS_SOAP_ENVELOPE(soap_envelope) || ! LASSO_SOAP_BODY(soap_envelope->Body))
|
|
return NULL;
|
|
|
|
fault = (LassoSoapFault*)_get_node(&soap_envelope->Body->any, LASSO_TYPE_SOAP_FAULT, NULL, NULL, NULL, create);
|
|
|
|
return fault;
|
|
}
|
|
|