diff options
author | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2009-08-26 15:13:46 +0000 |
---|---|---|
committer | Benjamin Dauvergne <bdauvergne@entrouvert.com> | 2009-08-26 15:13:46 +0000 |
commit | 55f20515343534d990b1cd9b0986fb159b47788e (patch) | |
tree | 728dd2641371e5b62586c5413ec2e3d65ffd0519 /lasso/id-wsf | |
parent | 59926d7545ecca45086484bd9bf60ffa7d7a8b12 (diff) | |
download | lasso-55f20515343534d990b1cd9b0986fb159b47788e.tar.gz lasso-55f20515343534d990b1cd9b0986fb159b47788e.tar.xz lasso-55f20515343534d990b1cd9b0986fb159b47788e.zip |
ID-WSF: Lots of modifications
Migrate lots of code to use new utility macros. Try to simplify most
code paths or to factorize with LassoWsfProfile.
* lasso/id-wsf/wsf_profile.c:
Add API:
- lasso_wsf_profile_build_soap_response_msg to build SOAP fault for
Lasso errors,
- lasso_wsf_profile_set_msg_url_from_description, to set the
destination URL using the chosen LassoDiscoDescription (with
respect to the security mechanism),
- lasso_wsf_profile_init_soap_response to initialize a response to
the current request, to use in sub classes,
- lasso_wsf_profile_get_remote_provider_id, retrieve the SOAP
binding corresponding information,
- lasso_wsf_profile_get_remote_provider, simplification of
lasso_wsf_profile_get_remote_provider_id,
- lasso_wsf_profile_get_soap_fault, retrieve the last setted SOAP
fault, used by sub classes,
- lasso_wsf_profile_set_soap_fault, set a SOAP fault, to be returned
by the next call by lasso_wsf_profile_build_soap_response_msg, to
use in sub classes,
- lasso_wsf_profile_set/get_status_code, set/get the stored status
code, to use in the next lasso_xxx_build_response_message, to use
in sub classes.
Change name lasso_wsf_profile_get_description_autos to
lasso_wsf_profile_get_description_auto.
Do not access directly the session is_dirty field (it has been
sealed).
* lasso/id-wsf/wsf_profile.h:
Add helper macro lasso_wsf_profile_helper_set_status to set status
code of an ID-WSF response message containing a Status element using
the stored status code.
* lasso/id-wsf/wsf_profile_private.h:
Add new fields (moved public fields).
Add lasso_wsf_profile_set_msg_url_from_description,
lasso_wsf_profile_build_soap_fault_response_msg.
* lasso/id-wsf/data_service_private.h:
Remove file.
* lasso/id-wsf/data_service.h: Remove all public fields.
* lasso/id-wsf/data_service.c:
Remove private structure. Use the equivalents LassoWsfProfile private
fields. Update documentation. Use LassoWsfProfile generic functions
for initializing requests. Add API lasso_data_service_get_query_item,
lasso_data_service_get_answers, lasso_data_service_get_answer,
lasso_data_service_get_answers_by_select,
lasso_data_service_get_answer_for_item_id,
lasso_data_service_add_modification.
Remove lasso_data_service_need_redirect_user use equivalent function
lasso_interaction_profile_service_build_redirect_response_msg. Remove
lasso_data_service_get_resource_offering,
lasso_data_service_set_offering.
* lasso/id-wsf/discovery.c:
Add documentation. Change some signatures. Remove
lasso_discovery_get_description_auto. Change name of
lasso_discovery_init_insert to lasso_discovery_init_modify. Add a
generic lasso_discovery_process_request_msg.
Add internal function lasso_discovery_init_offering, to get
automatically an offering if possible. Remove useless init_from_xml.
Rework lasso_discovery_build_credential implementation.
overloading. Remove lasso_discovery_destroy.
* lasso/id-wsf/discovery.h:
Remove lasso_discovery_destroy.
* lasso/id-wsf/interaction_profile_service.c:
Add lasso_interaction_profile_service_build_redirect_response_msg.
* lasso/id-wsf/personal_profile_service.c:
Update lasso_personal_profile_service_get_email to use
lasso_data_service_get_answers_by_select.
* lasso/xml/dst_modify.c:
make modification parameter optional to the constructor.
Diffstat (limited to 'lasso/id-wsf')
-rw-r--r-- | lasso/id-wsf/data_service.c | 1182 | ||||
-rw-r--r-- | lasso/id-wsf/data_service.h | 34 | ||||
-rw-r--r-- | lasso/id-wsf/data_service_private.h | 42 | ||||
-rw-r--r-- | lasso/id-wsf/discovery.c | 920 | ||||
-rw-r--r-- | lasso/id-wsf/discovery.h | 57 | ||||
-rw-r--r-- | lasso/id-wsf/interaction_profile_service.c | 36 | ||||
-rw-r--r-- | lasso/id-wsf/personal_profile_service.c | 69 | ||||
-rw-r--r-- | lasso/id-wsf/wsf_profile.c | 523 | ||||
-rw-r--r-- | lasso/id-wsf/wsf_profile.h | 52 | ||||
-rw-r--r-- | lasso/id-wsf/wsf_profile_private.h | 10 |
10 files changed, 1628 insertions, 1297 deletions
diff --git a/lasso/id-wsf/data_service.c b/lasso/id-wsf/data_service.c index 47cc1122..b25b1af9 100644 --- a/lasso/id-wsf/data_service.c +++ b/lasso/id-wsf/data_service.c @@ -63,7 +63,6 @@ #include <lasso/id-wsf/discovery.h> #include <lasso/id-wsf/data_service.h> -#include <lasso/id-wsf/data_service_private.h> #include <lasso/xml/dst_query.h> #include <lasso/xml/dst_query_response.h> #include <lasso/xml/dst_modify.h> @@ -76,129 +75,73 @@ #include <xmlsec/xmldsig.h> #include <xmlsec/templates.h> #include <xmlsec/crypto.h> +#include "./wsf_profile_private.h" extern GHashTable *dst_services_by_prefix; /* cf xml/xml.c */ -struct _LassoDataServicePrivate -{ - gboolean dispose_has_run; - LassoDiscoResourceOffering *offering; - GList *credentials; - LassoSoapFault *fault; -}; - static void lasso_register_idwsf_xpath_namespaces(xmlXPathContext *xpathCtx); +static gint lasso_data_service_apply_query(LassoDataService *service, + LassoDstQueryResponse *query_response, xmlXPathContext *xpathCtx, + LassoDstQueryItem *item); +G_GNUC_UNUSED static gint lasso_data_service_apply_queries(LassoDataService *service, + LassoDstQueryResponse *query_response, xmlNode *data, GList *queries); + + +struct _LassoDataServicePrivate { + xmlNode *resource_data; + LassoDiscoResourceID *ResourceID; + LassoDiscoResourceID *EncryptedResourceID; +}; /*****************************************************************************/ /* public methods */ /*****************************************************************************/ -gint -lasso_data_service_add_credential(LassoDataService *service, - LassoSamlAssertion *assertion) -{ - service->private_data->credentials = g_list_append( - service->private_data->credentials, - g_object_ref(assertion)); - return 0; -} - /** * lasso_data_service_init_query * @service: a #LassoDataService * @select: resource selection string (typically a XPath query) * @item_id: query item identifier (optional) * - * Initializes a new dst:Query request, asking for element @select (with - * optional itemID set to @item_id). @item_id may be NULL only if the query - * won't contain other query items. + * Initializes a new dst:Query request, asking for element @select (with optional itemID set to + * @item_id). @item_id may be NULL only if the query won't contain other query items. You must + * follow this constraint, it will not be checked. * - * If both @select and @item_id are NULL, only a skeleton request is created - * and calls to lasso_data_service_add_query_item() will need to be done. + * If both @select and @item_id are NULL, only a skeleton request is created and calls to + * lasso_data_service_add_query_item() will need to be done. * * Return value: 0 on success; or a negative value otherwise. **/ gint lasso_data_service_init_query(LassoDataService *service, const char *select, - const char *item_id, const char *security_mech_id) + const char *item_id, G_GNUC_UNUSED const char *security_mech_id) { - LassoWsfProfile *profile; - LassoDstQuery *query; - LassoDiscoResourceOffering *offering; - LassoDiscoDescription *description; - GList *iter; + LassoWsfProfile *wsf_profile = NULL; + LassoDstQuery *query = NULL; + LassoDiscoResourceOffering *offering = NULL; + gint rc = 0; - profile = LASSO_WSF_PROFILE(service); + lasso_bad_param(DATA_SERVICE, service); + wsf_profile = &service->parent; + /* 1. build the message content */ if (select) { query = lasso_dst_query_new(lasso_dst_query_item_new(select, item_id)); } else { query = lasso_dst_query_new(NULL); } - profile->request = LASSO_NODE(query); - - if (service == NULL || service->private_data == NULL - || service->private_data->offering == NULL) { - return LASSO_PROFILE_ERROR_MISSING_RESOURCE_OFFERING; - } - offering = service->private_data->offering; - - if (offering->ServiceInstance == NULL - || offering->ServiceInstance->ServiceType == NULL) { - return LASSO_PROFILE_ERROR_MISSING_SERVICE_TYPE; - } - query->hrefServiceType = g_strdup(offering->ServiceInstance->ServiceType); - query->prefixServiceType = lasso_get_prefix_for_dst_service_href( - query->hrefServiceType); - if (query->prefixServiceType == NULL) { - return LASSO_DATA_SERVICE_ERROR_UNREGISTERED_DST; - } - - if (offering->ResourceID) { - query->ResourceID = g_object_ref(offering->ResourceID); - } else if (offering->EncryptedResourceID) { - query->EncryptedResourceID = g_object_ref(offering->EncryptedResourceID); - } else { - /* XXX: no resource id, implied:resource, etc. */ - return LASSO_ERROR_UNIMPLEMENTED; - } - - lasso_wsf_profile_init_soap_request(LASSO_WSF_PROFILE(service), LASSO_NODE(query)); - - /* Set description */ - if (security_mech_id == NULL) { - description = LASSO_DISCO_DESCRIPTION(offering->ServiceInstance->Description->data); - } else { - description = lasso_discovery_get_description_auto(offering, security_mech_id); - } - if (description == NULL) { - return LASSO_PROFILE_ERROR_MISSING_SERVICE_DESCRIPTION; - } - lasso_wsf_profile_set_description(LASSO_WSF_PROFILE(service), description); - - /* Set msgUrl */ - if (description->Endpoint != NULL) { - profile->msg_url = g_strdup(description->Endpoint); - } else { - /* XXX: else, description->WsdlURLI, get endpoint automatically */ - return LASSO_ERROR_UNIMPLEMENTED; - } - - /* Added needed credential for remote service */ - if (description->CredentialRef) { - char *credentialRef = description->CredentialRef->data; - iter = service->private_data->credentials; - while (iter) { - LassoSamlAssertion *credential = LASSO_SAML_ASSERTION(iter->data); - if (strcmp(credentialRef, credential->AssertionID) == 0) { - /* lasso_wsf_profile_add_saml_authentication( - LASSO_WSF_PROFILE(service), credential); */ - iter = iter->next; - } - } - } - - return 0; + lasso_assign_string(query->hrefServiceType, offering->ServiceInstance->ServiceType); + lasso_assign_new_string(query->prefixServiceType, lasso_get_prefix_for_dst_service_href( + query->hrefServiceType)); + goto_cleanup_if_fail_with_rc (query->prefixServiceType != NULL, + LASSO_DATA_SERVICE_ERROR_UNREGISTERED_DST); + + /* 2. build the envelope */ + rc = lasso_wsf_profile_init_soap_request(wsf_profile, &query->parent); + +cleanup: + lasso_release_gobject(query); + return rc; } /** @@ -207,39 +150,81 @@ lasso_data_service_init_query(LassoDataService *service, const char *select, * @select: resource selection string (typically a XPath query) * @item_id: query item identifier * - * Adds a dst:QueryItem to the current dst:Query request. + * Adds a dst:QueryItem to the current dst:Query request. If there are already query item in the + * request and @itemId is NULL, the call will fail. * - * Return value: a newly created #LassoDstQueryItem with the query item that - * has been created. Note that it is internally allocated and shouldn't - * be freed by the caller. + * Return value: 0 if sucessfull, an error code otherwise. **/ -LassoDstQueryItem* +gint lasso_data_service_add_query_item(LassoDataService *service, const char *select, const char *item_id) { - LassoDstQuery *query; - LassoDstQueryItem *item; - - g_return_val_if_fail(LASSO_IS_DATA_SERVICE(service), NULL); - g_return_val_if_fail(select != NULL, NULL); - - if (! LASSO_IS_DST_QUERY(LASSO_WSF_PROFILE(service)->request)) { - return NULL; + LassoWsfProfile *wsf_profile; + LassoDstQuery *query = NULL; + int rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + wsf_profile = &service->parent; + + lasso_return_val_if_invalid_param(DST_QUERY, wsf_profile->request, + LASSO_PROFILE_ERROR_MISSING_REQUEST); + query = (LassoDstQuery*)wsf_profile->request; + + /** Check that we can add a new item */ + if (query->QueryItem && ( + (query->QueryItem->data && + (! LASSO_IS_DST_QUERY_ITEM(query->QueryItem->data) || + LASSO_DST_QUERY_ITEM(query->QueryItem->data)->itemID == NULL)) || + (item_id == NULL))) { + return LASSO_DATA_SERVICE_CANNOT_ADD_ITEM; } - query = LASSO_DST_QUERY(LASSO_WSF_PROFILE(service)->request); + lasso_list_add_new_gobject(query->QueryItem, lasso_dst_query_item_new(select, item_id)); - if (query->QueryItem && query->QueryItem->data && - LASSO_DST_QUERY_ITEM(query->QueryItem->data)->itemID == NULL) { - /* XXX: all items must have itemID if there is more than one, - * perhaps we could generate an item id for those lacking it */ - return NULL; - } + return rc; +} - item = lasso_dst_query_item_new(select, item_id); - query->QueryItem = g_list_append(query->QueryItem, item); +/** + * lasso_data_service_get_query_item: + * @service: a #LassoDataService + * @select: the select string of the query item to found + * @item_id: the item id of the query item to found + * @output: a #LassoDstQueryItem handle to store the result object, its reference count is not + * incremented. + * + * Look up the first query item in the current request matching the given criteria, @select or + * @item_id. At least one of the criteria must be present for the call to succeed. + * + * Return value: 0 if successful, an error code otherwise. + */ +gint +lasso_data_service_get_query_item(LassoDataService *service, + const char *select, const char *item_id, LassoDstQueryItem **output) +{ + LassoDstQuery *query = NULL; + GList *query_items = NULL; + LassoWsfProfile *wsf_profile = NULL; + gint rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + g_return_val_if_fail(select || item_id, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + wsf_profile = &service->parent; + lasso_extract_node_or_fail(query, wsf_profile->request, DST_QUERY, LASSO_PROFILE_ERROR_MISSING_REQUEST); + lasso_foreach(query_items, query->QueryItem) + { + LassoDstQueryItem *query_item = NULL; + lasso_extract_node_or_fail(query_item, query_items->data, DST_QUERY_ITEM, LASSO_ERROR_CAST_FAILED); + if ((select && g_strcmp0(select, query_item->Select)) || + (item_id && g_strcmp0(item_id, query_item->itemID))) + { + if (output) { + lasso_assign_new_gobject(*output, query_item); + } + } + } - return item; +cleanup: + return rc; } /** @@ -256,71 +241,35 @@ gint lasso_data_service_process_query_msg(LassoDataService *service, const char *message, const char *security_mech_id) { - LassoDstQuery *query; - LassoWsfProfile *profile; - int rc; - gchar *service_type; - GList *node_list; - LassoSoapEnvelope *envelope; - xmlDoc *doc; - xmlNode *xmlnode; - - /* FIXME: another way to get the service type ? */ - - g_return_val_if_fail(message != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - - doc = lasso_xml_parse_memory(message, strlen(message)); - if (doc == NULL) { - return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG); - } - - xmlnode = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature, - xmlSecDSigNs); - if (xmlnode) { - xmlUnlinkNode(xmlnode); - xmlFreeNode(xmlnode); - xmlnode = NULL; - } - - envelope = LASSO_SOAP_ENVELOPE(lasso_node_new_from_xmlNode(xmlDocGetRootElement(doc))); - if (envelope->Body == NULL || envelope->Body->any == NULL - || envelope->Body->any->data == NULL) { - return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG); - } - query = LASSO_DST_QUERY(envelope->Body->any->data); - service_type = g_strdup(query->hrefServiceType); - lasso_release_doc(doc); - - profile = LASSO_WSF_PROFILE(service); - rc = lasso_wsf_profile_process_soap_request_msg(profile, message, service_type, - security_mech_id); - if (rc) { - return rc; - } - - /* get provider id from soap:Header */ - for (node_list = profile->soap_envelope_request->Header->Other; - node_list; node_list = g_list_next(node_list)) { - LassoNode *node = node_list->data; - if (LASSO_IS_SOAP_BINDING_PROVIDER(node)) { - if (service->provider_id) - g_free(service->provider_id); - service->provider_id = g_strdup( - LASSO_SOAP_BINDING_PROVIDER(node)->providerID); - } - } - - if (query->ResourceID) { - service->resource_id = g_object_ref(query->ResourceID); - } else if (query->EncryptedResourceID) { - service->encrypted_resource_id = g_object_ref(query->EncryptedResourceID); - } else { - return LASSO_ERROR_UNIMPLEMENTED; /* implied ? */ - } - - return 0; + LassoWsfProfile *wsf_profile = NULL; + LassoDstQuery *query = NULL; + LassoDstQueryResponse *query_response = NULL; + gchar *service_type = NULL; + int rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + lasso_null_param(message); + wsf_profile = &service->parent; + + rc = lasso_wsf_profile_process_soap_request_msg(wsf_profile, message, security_mech_id); + goto_cleanup_if_fail(! rc); + + lasso_return_val_if_invalid_param(DST_QUERY, wsf_profile->request, + LASSO_PROFILE_ERROR_MISSING_REQUEST); + + query = (LassoDstQuery*)wsf_profile->request; + lasso_assign_string(service_type, query->hrefServiceType); + + lasso_wsf_profile_helper_assign_resource_id(service->private_data, query); + query_response = lasso_dst_query_response_new(NULL); + /* FIXME: initialize the response object */ + rc = lasso_wsf_profile_init_soap_response(wsf_profile, LASSO_NODE(query_response)); +cleanup: + lasso_release_gobject(query_response); + return rc; } + /** * lasso_data_service_build_response_msg: * @service: a #LassoDataService @@ -330,190 +279,268 @@ lasso_data_service_process_query_msg(LassoDataService *service, const char *mess * Return value: 0 on success; or a negative value otherwise. **/ gint -lasso_data_service_build_response_msg(LassoDataService *service) +lasso_data_service_build_query_response_msg(LassoDataService *service) { - LassoWsfProfile *profile; - LassoDstQuery *request; - LassoDstQueryResponse *response; - GList *iter; - xmlDoc *doc; - xmlXPathContext *xpathCtx; - xmlXPathObject *xpathObj; - LassoSoapEnvelope *envelope; + LassoWsfProfile *wsf_profile = NULL; + LassoDstQuery *request = NULL; + LassoDstQueryResponse *response = NULL; + LassoSoapEnvelope *envelope = NULL; + gint rc = 0; - profile = LASSO_WSF_PROFILE(service); - request = LASSO_DST_QUERY(profile->request); + lasso_bad_param(DATA_SERVICE, service); + wsf_profile = &service->parent; + lasso_extract_node_or_fail(request, wsf_profile->request, DST_QUERY, LASSO_PROFILE_ERROR_MISSING_REQUEST); - envelope = profile->soap_envelope_response; - - if (service->private_data->fault != NULL) { - envelope->Body->any = g_list_append( - envelope->Body->any, service->private_data->fault); - return lasso_wsf_profile_build_soap_response_msg(profile); - } + envelope = wsf_profile->soap_envelope_response; response = lasso_dst_query_response_new( lasso_utility_status_new(LASSO_DST_STATUS_CODE_OK)); - profile->response = LASSO_NODE(response); + wsf_profile->response = LASSO_NODE(response); response->prefixServiceType = g_strdup(request->prefixServiceType); response->hrefServiceType = g_strdup(request->hrefServiceType); envelope->Body->any = g_list_append(envelope->Body->any, response); - doc = xmlNewDoc((xmlChar*)"1.0"); - xmlDocSetRootElement(doc, service->resource_data); - xpathCtx = xmlXPathNewContext(doc); - lasso_register_idwsf_xpath_namespaces(xpathCtx); - /* XXX: needs another level, since there may be more than one <dst:Query> */ - iter = request->QueryItem; - while (iter) { - LassoDstQueryItem *item = iter->data; - LassoDstData *data; + return lasso_wsf_profile_build_soap_response_msg(wsf_profile); +cleanup: + return rc; +} - xpathObj = xmlXPathEvalExpression((xmlChar*)item->Select, xpathCtx); - if (xpathObj && xpathObj->nodesetval && xpathObj->nodesetval->nodeNr) { - xmlNode *node = xpathObj->nodesetval->nodeTab[0]; - /* XXX: assuming there is only one matching node */ - data = lasso_dst_data_new(); - data->any = g_list_append(data->any, xmlCopyNode(node, 1)); - } else if (xpathObj && xpathObj->type == XPATH_STRING) { - data = lasso_dst_data_new(); - data->any = g_list_append(data->any, - xmlNewText(xpathObj->stringval)); - } else { - /* no response was found, break here */ - if (xpathObj) { - xmlXPathFreeObject(xpathObj); +/** + * lasso_data_service_get_answers: + * @service: a #LassoDataService object. + * @output: an xmlNode** pointer where to put the xmlNode* of the result + * + * Get all the xmlNode content of the first Data element of the QueryResponse message. + * + * Return value: 0 if sucessful, an error code otherwise. + */ +gint +lasso_data_service_get_answers(LassoDataService *service, GList **output) +{ + LassoDstQueryResponse *query_response = NULL; + LassoDstData *data = NULL; + LassoWsfProfile *wsf_profile = NULL; + GList *datas = NULL; + int rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + wsf_profile = &service->parent; + lasso_extract_node_or_fail(query_response, wsf_profile->request, DST_QUERY_RESPONSE, + LASSO_PROFILE_ERROR_MISSING_REQUEST); + + datas = query_response->Data; + + if (datas) { + lasso_extract_node_or_fail(data, datas->data, DST_DATA, + LASSO_ERROR_CAST_FAILED); + } + + if (data) { + if (output) { + GList *data_content = data->any; + lasso_release_list_of_xml_node(*output); + for (;data_content; data_content = g_list_next(data_content)) { + lasso_list_add_xml_node(*output, data_content->data); } - break; } - if (item->itemID) { - data->itemIDRef = g_strdup(item->itemID); - } - response->Data = g_list_append(response->Data, data); - xmlXPathFreeObject(xpathObj); - xpathObj = NULL; - iter = g_list_next(iter); + } else { + rc = LASSO_DST_ERROR_NO_DATA; } - xmlUnlinkNode(service->resource_data); - xmlXPathFreeContext(xpathCtx); - lasso_release_doc(doc); +cleanup: + return rc; +} +/** + * lasso_data_service_get_answer: + * @service: a #LassoDataService object. + * @output: an xmlNode** pointer where to put the xmlNode* of the result + * + * Get the first xmlNode of the first Data element of the QueryResponse message. + * + * Return value: 0 if sucessful, an error code otherwise. + */ +gint +lasso_data_service_get_answer(LassoDataService *service, xmlNode **output) +{ + LassoDstQueryResponse *query_response = NULL; + LassoDstData *data = NULL; + LassoWsfProfile *wsf_profile = NULL; + GList *datas = NULL; + int rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + wsf_profile = &service->parent; + lasso_extract_node_or_fail(query_response, wsf_profile->request, DST_QUERY_RESPONSE, + LASSO_PROFILE_ERROR_MISSING_REQUEST); + + datas = query_response->Data; + + if (datas) { + lasso_extract_node_or_fail(data, datas->data, DST_DATA, + LASSO_ERROR_CAST_FAILED); + } + + if (data) { + if (output) { + xmlNode *first_element = NULL; + if (data->any) { + first_element = data->any->data; + } + lasso_assign_xml_node(*output, first_element); + } + } else { + rc = LASSO_DST_ERROR_NO_DATA; + } - return lasso_wsf_profile_build_soap_response_msg(profile); +cleanup: + return rc; } /** - * lasso_data_service_get_answer: + * lasso_data_service_get_answers_by_select: * @service: a #LassoDataService * @select: resource selection string (typically a XPath query) + * @output: a GList** to store a GList* containing the result, it must be freed. + * + * Returns the answers for the specified @select request. * - * Returns the answer for the specified @select request. + * Return value: 0 if successful, an error code otheriwse * - * Return value: the node (libxml2 xmlNode*); or NULL if it was not found. - * This xmlnode must be freed by caller. **/ -xmlNode* -lasso_data_service_get_answer(LassoDataService *service, const char *select) +gint +lasso_data_service_get_answers_by_select(LassoDataService *service, const char *select, GList **output) { - LassoDstQueryResponse *response; + LassoDstQuery *query = NULL; + LassoDstQueryResponse *query_response = NULL; LassoDstData *data = NULL; - GList *iter; - char *item_id = NULL; - - response = LASSO_DST_QUERY_RESPONSE(LASSO_WSF_PROFILE(service)->response); - iter = LASSO_DST_QUERY(LASSO_WSF_PROFILE(service)->request)->QueryItem; - - if (select == NULL) { - /* if only one element; default to first */ - if (g_list_length(iter) > 1) - return NULL; - if (response->Data == NULL) - return NULL; - data = response->Data->data; + LassoWsfProfile *wsf_profile = NULL; + LassoDstQueryItem *query_item = NULL; + GList *iter = NULL; + GList *datas = NULL; + int rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + lasso_null_param(select); + wsf_profile = &service->parent; + lasso_extract_node_or_fail(query, wsf_profile->request, DST_QUERY, + LASSO_PROFILE_ERROR_MISSING_REQUEST); + lasso_extract_node_or_fail(query_response, wsf_profile->request, DST_QUERY_RESPONSE, + LASSO_PROFILE_ERROR_MISSING_REQUEST); + + iter = query->QueryItem; + datas = query_response->Data; + + /* one query, no need for itemID, data is the first one, or absent */ + if (iter && iter->next == NULL) { + lasso_extract_node_or_fail(query_item, iter->data, DST_QUERY_ITEM, + LASSO_ERROR_CAST_FAILED); + + if (datas) { + lasso_extract_node_or_fail(data, datas->data, DST_DATA, + LASSO_ERROR_CAST_FAILED); + if (g_strcmp0(select, query_item->Select) != 0) { + data = NULL; + rc = LASSO_DST_ERROR_QUERY_NOT_FOUND; + } + } else { + rc = LASSO_DST_ERROR_NO_DATA; + } + /* many queries */ } else { - LassoDstQueryItem *item = NULL; /* lookup select in query to get itemId, then get data with itemIdRef */ - /* XXX: needs another level, since there may be more than one dst:Query */ while (iter) { - item = iter->data; - iter = g_list_next(iter); - if (strcmp(item->Select, select) == 0) { + lasso_extract_node_or_fail(query_item, iter->data, DST_QUERY_ITEM, + LASSO_ERROR_CAST_FAILED); + if (g_strcmp0(query_item->Select, select) == 0) { break; } - item = NULL; - } - - iter = LASSO_DST_QUERY(LASSO_WSF_PROFILE(service)->request)->QueryItem; - if (item == NULL) { - /* not found */ - return NULL; + query_item = NULL; + iter = g_list_next(iter); } - item_id = item->itemID; - if (item_id == NULL) { - /* item_id is not mandatory when there is only one item */ - if (response->Data == NULL) - return NULL; - data = response->Data->data; + if (query_item && ! query_item->itemID) { + goto_cleanup_with_rc(LASSO_DST_ERROR_MALFORMED_QUERY); } - iter = response->Data; - while (iter && item_id) { - LassoDstData *t = iter->data; - iter = g_list_next(iter); - if (strcmp(t->itemIDRef, item_id) == 0) { - data = t; + while (datas) { + lasso_extract_node_or_fail(data, datas->data, DST_DATA, + LASSO_ERROR_CAST_FAILED); + if (g_strcmp0(data->itemIDRef, query_item->itemID) == 0) { break; } + data = NULL; + datas = g_list_next(datas); } - if (data == NULL) { - /* not found */ - return NULL; + } + + if (data) { + if (output) { + GList *data_content = data->any; + lasso_release_list_of_xml_node(*output); + for (;data_content; data_content = g_list_next(data_content)) { + lasso_list_add_xml_node(*output, data_content->data); + } } + } else { + rc = LASSO_DST_ERROR_NO_DATA; } - /* XXX: there may be more than one xmlnode */ - return xmlCopyNode(data->any->data, 1); +cleanup: + return rc; } /** * lasso_data_service_get_answer_for_item_id: * @service: a #LassoDataService * @item_id: query item identifier + * @output: a GList** to store a GList* containing the result, it must be freed. + * + * Returns the answers for the specified @itemID request. * - * Returns the answer for the specified @item_id query item. + * Return value: 0 if successful, an error code otherwise * - * Return value: the node (libxml2 xmlNode*); or NULL if it was not found. - * This xmlnode must be freed by caller. **/ -xmlNode* -lasso_data_service_get_answer_for_item_id(LassoDataService *service, const char *item_id) +gint +lasso_data_service_get_answers_by_item_id(LassoDataService *service, const char *item_id, GList **output) { - LassoDstQueryResponse *response; + LassoDstQueryResponse *query_response = NULL; LassoDstData *data = NULL; - GList *iter; - - response = LASSO_DST_QUERY_RESPONSE(LASSO_WSF_PROFILE(service)->response); - - iter = response->Data; - while (iter && item_id) { - LassoDstData *t = iter->data; - iter = g_list_next(iter); - if (strcmp(t->itemIDRef, item_id) == 0) { - data = t; + LassoWsfProfile *wsf_profile = NULL; + GList *datas = NULL; + int rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + lasso_null_param(select); + wsf_profile = &service->parent; + lasso_extract_node_or_fail(query_response, wsf_profile->request, DST_QUERY_RESPONSE, + LASSO_PROFILE_ERROR_MISSING_REQUEST); + + datas = query_response->Data; + while (datas) { + lasso_extract_node_or_fail(data, datas->data, DST_DATA, LASSO_ERROR_CAST_FAILED); + if (g_strcmp0(data->itemIDRef, item_id) == 0) { break; } + data = NULL; + datas = g_list_next(datas); } - if (data == NULL) { - /* not found */ - return NULL; + + if (data) { + if (output) { + GList *data_content = data->any; + lasso_release_list_of_xml_node(*output); + for (;data_content; data_content = g_list_next(data_content)) { + lasso_list_add_xml_node(*output, data_content->data); + } + } + } else { + rc = LASSO_DST_ERROR_NO_DATA; } - /* XXX: there may be more than one xmlnode */ - return xmlCopyNode(data->any->data, 1); +cleanup: + return rc; } - /** * lasso_data_service_process_query_response_msg: * @service: a #LassoDataService @@ -528,53 +555,14 @@ gint lasso_data_service_process_query_response_msg(LassoDataService *service, const char *message) { - int rc; - LassoSoapFault *fault = NULL; - LassoIsRedirectRequest *redirect_request = NULL; - GList *iter; + int rc = 0; rc = lasso_wsf_profile_process_soap_response_msg(LASSO_WSF_PROFILE(service), message); - if (rc) return rc; - - /* Process Soap Faults response */ - iter = LASSO_WSF_PROFILE(service)->soap_envelope_response->Body->any; - while (iter) { - if (LASSO_IS_SOAP_FAULT(iter->data) == TRUE) { - fault = LASSO_SOAP_FAULT(iter->data); - break; - } - iter = iter->next; - } - if (!fault) - return 0; - - iter = fault->Detail->any; - while (iter) { - if (LASSO_IS_IS_REDIRECT_REQUEST(iter->data) == TRUE) { - redirect_request = LASSO_IS_REDIRECT_REQUEST(iter->data); - break; - } - iter = iter->next; + if (! rc && ! LASSO_IS_DST_QUERY_RESPONSE(service->parent.response)) { + rc = LASSO_PROFILE_ERROR_MISSING_RESPONSE; } - if (redirect_request) - return LASSO_SOAP_FAULT_REDIRECT_REQUEST; - - return 0; -} - -gint -lasso_data_service_need_redirect_user(LassoDataService *service, const char *redirectUrl) -{ - LassoSoapDetail *detail; - - /* Find a SOAP fault element */ - service->private_data->fault = lasso_soap_fault_new(); - service->private_data->fault->faultcode = g_strdup(LASSO_SOAP_FAULT_CODE_SERVER); - detail = lasso_soap_detail_new(); - detail->any = g_list_append(detail->any, lasso_is_redirect_request_new(redirectUrl)); - service->private_data->fault->Detail = detail; - return 0; + return rc; } /** @@ -623,144 +611,173 @@ lasso_data_service_get_redirect_request_url(LassoDataService *service) return g_strdup(redirect_request->redirectURL); } +/** + * lasso_data_service_init_modify: + * @service: a #LassoDataService object + * @select: an Select command (usually using the XPath syntax) + * @xmlData: the XML data for replacing the data + * + * Initialize a Data Service Template Modify request using a command to select some data, and an XML + * fragment to replace the selected data. + * + * Return value: 0 if successful, an error code otherwise. + */ gint -lasso_data_service_init_modify(LassoDataService *service, const gchar *select, - xmlNode *xmlData) +lasso_data_service_init_modify(LassoDataService *service) { - LassoDstModification *modification; - LassoDstNewData *newData; - LassoDiscoResourceOffering *offering; - LassoDiscoDescription *description = NULL; - LassoWsfProfile *profile; - LassoDstModify *modify; + LassoDiscoResourceOffering *offering = NULL; + LassoWsfProfile *wsf_profile = NULL; + LassoDstModify *modify = NULL; + gint rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + lasso_null_param(service); + + wsf_profile = &service->parent; + /* Build the Modify request */ + modify = lasso_dst_modify_new(NULL); + + offering = lasso_wsf_profile_get_resource_offering(wsf_profile); + goto_cleanup_if_fail_with_rc (offering, LASSO_PROFILE_ERROR_MISSING_RESOURCE_OFFERING); + goto_cleanup_if_fail_with_rc (offering->ServiceInstance != NULL && + offering->ServiceInstance->ServiceType != NULL, + LASSO_PROFILE_ERROR_MISSING_SERVICE_TYPE); + lasso_assign_string(modify->hrefServiceType, offering->ServiceInstance->ServiceType); + lasso_assign_new_string(modify->prefixServiceType, lasso_get_prefix_for_dst_service_href( + modify->hrefServiceType)); + goto_cleanup_if_fail_with_rc (modify->prefixServiceType != NULL, LASSO_DATA_SERVICE_ERROR_UNREGISTERED_DST); + lasso_wsf_profile_helper_assign_resource_id(modify, offering); + + rc = lasso_wsf_profile_init_soap_request(wsf_profile, &modify->parent); +cleanup: + lasso_release_gobject(modify); + return rc; +} - g_return_val_if_fail(LASSO_IS_DATA_SERVICE(service), - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(service != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - g_return_val_if_fail(xmlData != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); +/** + * lasso_data_service_add_modification: + * @service: a #LassoDataService object + * @select: a selector string + * @xmlData: optional NewData content + * @overrideAllowed: wheter to permit delete or replace of existings + * @notChagendSince: if not NULL, give the time (as a local time_t value) of the last known + * modification to the datas, it is used to permit secure concurrent accesses. + * + * Add a new modification to the current modify request. If overrideAllowed is FALSE, xmlData must + * absolutely be present. Refer to the ID-WSF DST 1.0 specification for the semantic of the created + * message. + * + * Return value: 0 if successful and the new modification object in *output, an error code + * otherwise. + */ +gint +lasso_data_service_add_modification(LassoDataService *service, const gchar *select, + xmlNode *xmlData, gboolean overrideAllowed, time_t *notChangedSince, + LassoDstModification **output) +{ + LassoWsfProfile *wsf_profile = NULL; + LassoDstModification *modification = NULL; + LassoDstNewData *newData = NULL; + LassoDstModify *modify = NULL; + gint rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + lasso_null_param(select); - profile = LASSO_WSF_PROFILE(service); + wsf_profile = &service->parent; + lasso_extract_node_or_fail(modify, wsf_profile->request, DST_MODIFY, + LASSO_ERROR_CAST_FAILED); - /* init Modify */ modification = lasso_dst_modification_new(select); newData = lasso_dst_new_data_new(); - newData->any = g_list_append(newData->any, xmlCopyNode(xmlData, 1)); - modification->NewData = newData; - - modify = lasso_dst_modify_new(modification); - profile->request = LASSO_NODE(modify); - - if (service == NULL || service->private_data == NULL - || service->private_data->offering == NULL) { - return LASSO_PROFILE_ERROR_MISSING_RESOURCE_OFFERING; - } - offering = service->private_data->offering; - - if (offering->ServiceInstance == NULL - || offering->ServiceInstance->ServiceType == NULL) { - return LASSO_PROFILE_ERROR_MISSING_SERVICE_TYPE; + lasso_release_list_of_xml_node(newData->any); + lasso_list_add_xml_node(newData->any, xmlData); + lasso_assign_new_gobject(modification->NewData, newData); + lasso_list_add_new_gobject(modify->Modification, + modification); + modification->overrideAllowed = overrideAllowed; + if (notChangedSince) { + lasso_assign_new_string(modification->notChangedSince, + lasso_time_to_iso_8601_gmt(*notChangedSince)); } - modify->hrefServiceType = g_strdup(offering->ServiceInstance->ServiceType); - modify->prefixServiceType = lasso_get_prefix_for_dst_service_href( - modify->hrefServiceType); - if (modify->prefixServiceType == NULL) { - return LASSO_DATA_SERVICE_ERROR_UNREGISTERED_DST; - } - - /* get ResourceID / EncryptedResourceID */ - if (offering->ResourceID) { - modify->ResourceID = offering->ResourceID; - } else if (offering->EncryptedResourceID) { - modify->EncryptedResourceID = offering->EncryptedResourceID; - } else { - /* XXX: no resource id, implied:resource, etc. */ - return LASSO_ERROR_UNIMPLEMENTED; - } - - lasso_wsf_profile_init_soap_request(LASSO_WSF_PROFILE(service), LASSO_NODE(modify)); - /* Set description */ - if (offering->ServiceInstance != NULL && offering->ServiceInstance->Description != NULL) { - description = LASSO_DISCO_DESCRIPTION(offering->ServiceInstance->Description->data); - } - if (description == NULL) { - return LASSO_PROFILE_ERROR_MISSING_SERVICE_DESCRIPTION; - } - lasso_wsf_profile_set_description(LASSO_WSF_PROFILE(service), description); - - /* Set msgUrl */ - if (description->Endpoint != NULL) { - profile->msg_url = g_strdup(description->Endpoint); - } else { - /* XXX: else, description->WsdlURLI, get endpoint automatically */ - return LASSO_ERROR_UNIMPLEMENTED; + if (*output) { + lasso_assign_gobject(*output, modification); } - return 0; +cleanup: + return rc; } -LassoDstModification* -lasso_data_service_add_modification(LassoDataService *service, const gchar *select) +static gint +lasso_data_service_apply_modification(G_GNUC_UNUSED LassoDataService *service, G_GNUC_UNUSED LassoDstModification *modification, G_GNUC_UNUSED xmlXPathContext *xpath_ctxt) { - LassoWsfProfile *profile; - LassoDstModification *modification; + gint rc = 0; + return rc; +} - g_return_val_if_fail(LASSO_IS_DATA_SERVICE(service), NULL); - g_return_val_if_fail(select != NULL, NULL); +G_GNUC_UNUSED static gint +lasso_data_service_apply_modifications(LassoDataService *service, GList *modifications, xmlXPathContext *xpath_ctxt) +{ + gint rc = 0; + GList *i; - profile = LASSO_WSF_PROFILE(service); + lasso_foreach(i, modifications) { + LassoDstModification *dst_modification; - modification = lasso_dst_modification_new(select); - LASSO_DST_MODIFY(profile->request)->Modification = g_list_append( - LASSO_DST_MODIFY(profile->request)->Modification, (gpointer)modification); - - return modification; + if (LASSO_IS_DST_MODIFICATION(i->data)) { + rc = lasso_data_service_apply_modification(service, dst_modification, xpath_ctxt); + // First error, stop + if (rc) { + break; + } + } + } + return rc; } gint lasso_data_service_build_modify_response_msg(LassoDataService *service) { - LassoWsfProfile *profile; - LassoDstModify *request; - LassoDstModifyResponse *response; - LassoSoapEnvelope *envelope; - GList *iter; - xmlNode *cur_data; - xmlDoc *doc; - xmlXPathContext *xpathCtx; - xmlXPathObject *xpathObj; - int res = 0; + LassoWsfProfile *wsf_profile = NULL; + LassoDstModify *request = NULL; + LassoDstModifyResponse *response = NULL; + GList *iter = NULL; + xmlNode *cur_data = NULL; + xmlDoc *doc = NULL; + xmlXPathContext *xpathCtx = NULL; + xmlXPathObject *xpathObj = NULL; GList *node_to_free = NULL; + int res = 0; + xmlNode* resource_data; + gint rc = 0; - profile = LASSO_WSF_PROFILE(service); - request = LASSO_DST_MODIFY(profile->request); - - if (service->private_data->fault != NULL) { - envelope = profile->soap_envelope_response; - envelope->Body->any = g_list_append( - envelope->Body->any, service->private_data->fault); - return lasso_wsf_profile_build_soap_response_msg(profile); - } + lasso_bad_param(DATA_SERVICE, service); + wsf_profile = &service->parent; + g_return_val_if_fail(service->private_data, LASSO_PARAM_ERROR_NON_INITIALIZED_OBJECT); + lasso_extract_node_or_fail(request, wsf_profile->request, DST_MODIFY, + LASSO_PROFILE_ERROR_MISSING_REQUEST); + resource_data = service->private_data->resource_data; - if (service->resource_data == NULL) { + if (resource_data == NULL) { return LASSO_DST_ERROR_MISSING_SERVICE_DATA; } else { - cur_data = xmlCopyNode(service->resource_data, 1); + cur_data = xmlCopyNode(resource_data, 1); } + /* Build the Response object */ response = lasso_dst_modify_response_new( lasso_utility_status_new(LASSO_DST_STATUS_CODE_OK)); - profile->response = LASSO_NODE(response); - response->prefixServiceType = g_strdup(request->prefixServiceType); - response->hrefServiceType = g_strdup(request->hrefServiceType); - envelope = profile->soap_envelope_response; - envelope->Body->any = g_list_append(envelope->Body->any, response); + lasso_assign_string(response->prefixServiceType, request->prefixServiceType); + lasso_assign_string(response->hrefServiceType, request->hrefServiceType); + /* Create the XPath workbench */ doc = xmlNewDoc((xmlChar*)"1.0"); xmlDocSetRootElement(doc, cur_data); xpathCtx = xmlXPathNewContext(doc); lasso_register_idwsf_xpath_namespaces(xpathCtx); + /* Apply modifications */ for (iter = request->Modification; iter != NULL; iter = g_list_next(iter)) { LassoDstModification *modification = iter->data; xmlNode *newNode = modification->NewData->any->data; @@ -791,61 +808,54 @@ lasso_data_service_build_modify_response_msg(LassoDataService *service) if (res == 0 && doc->children != NULL) { /* Save new service resource data */ xmlNode *root = xmlDocGetRootElement(doc); - xmlFreeNode(service->resource_data); - service->resource_data = xmlCopyNode(root,1); + lasso_assign_xml_node(service->private_data->resource_data, root); } + rc = lasso_wsf_profile_build_soap_response_msg(wsf_profile); +cleanup: xmlXPathFreeContext(xpathCtx); g_list_foreach(node_to_free, (GFunc)xmlFreeNode, NULL); lasso_release_doc(doc); lasso_release_list(node_to_free); - - return lasso_wsf_profile_build_soap_response_msg(profile); + return rc; } +/** + * lasso_data_service_process_modify_msg: + * @service: a #LassoDataService object + * @modify_soap_msg: the SOAP request string + * @security_mech_id: the security mechanism to apply + * + * Parse the given request message, and initialize needed structures. + * + * Return value: 0 if successful, an error code otherwise. + */ gint lasso_data_service_process_modify_msg(LassoDataService *service, const gchar *modify_soap_msg, const gchar *security_mech_id) { - LassoDstModify *modify; - LassoWsfProfile *profile; - LassoSoapEnvelope *envelope; - xmlDoc *doc; - int rc; - gchar *service_type; - - - doc = lasso_xml_parse_memory(modify_soap_msg, strlen(modify_soap_msg)); - if (doc == NULL) { - return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG); - } - - envelope = LASSO_SOAP_ENVELOPE(lasso_node_new_from_xmlNode(xmlDocGetRootElement(doc))); - if (envelope->Body == NULL || envelope->Body->any == NULL - || envelope->Body->any->data == NULL) { - return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG); - } - - modify = LASSO_DST_MODIFY(envelope->Body->any->data); - service_type = g_strdup(modify->hrefServiceType); - lasso_release_doc(doc); - - profile = LASSO_WSF_PROFILE(service); - rc = lasso_wsf_profile_process_soap_request_msg(profile, modify_soap_msg, service_type, - security_mech_id); - if (rc) { - return rc; - } - - if (modify->ResourceID) { - service->resource_id = g_object_ref(modify->ResourceID); - } else if (modify->EncryptedResourceID) { - service->encrypted_resource_id = g_object_ref(modify->EncryptedResourceID); - } else { - return LASSO_ERROR_UNIMPLEMENTED; /* implied ? */ - } - - return 0; + LassoDstModify *modify = NULL; + LassoDstModifyResponse *modify_response = NULL; + LassoWsfProfile *wsf_profile = NULL; + int rc = 0; + + lasso_bad_param(DATA_SERVICE, service); + lasso_null_param(modify_soap_msg); + + wsf_profile = &service->parent; + + rc = lasso_wsf_profile_process_soap_request_msg(wsf_profile, modify_soap_msg, security_mech_id); + goto_cleanup_if_fail(! rc); + goto_cleanup_if_fail_with_rc( ! LASSO_IS_DST_MODIFY(wsf_profile->request), + LASSO_PROFILE_ERROR_MISSING_RESPONSE); + + modify = (LassoDstModify*)wsf_profile->request; + lasso_wsf_profile_helper_assign_resource_id(service->private_data, modify); + modify_response = lasso_dst_modify_response_new(NULL); + rc = lasso_wsf_profile_init_soap_response(wsf_profile, LASSO_NODE(modify_response)); +cleanup: + lasso_release_gobject(modify_response); + return rc; } /** @@ -853,43 +863,25 @@ lasso_data_service_process_modify_msg(LassoDataService *service, * @service: a #LassoDataService * @soap_msg: the SOAP message * + * Process a modify response message. + * * Return value: 0 on success; or a negative value otherwise. **/ gint lasso_data_service_process_modify_response_msg(LassoDataService *service, const gchar *soap_msg) { - LassoDstModifyResponse *response; - LassoSoapEnvelope *envelope; + int rc = 0; - g_return_val_if_fail(LASSO_IS_DATA_SERVICE(service), - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(soap_msg != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + lasso_bad_param(DATA_SERVICE, service); + lasso_null_param(soap_msg); - envelope = LASSO_SOAP_ENVELOPE(lasso_node_new_from_dump(soap_msg)); - if (envelope == NULL || ! envelope->Body || ! envelope->Body->any || - ! LASSO_IS_NODE(envelope->Body->any->data)) { - return critical_error(LASSO_PROFILE_ERROR_INVALID_MSG); - } + rc = lasso_wsf_profile_process_soap_response_msg(&service->parent, soap_msg); - LASSO_WSF_PROFILE(service)->soap_envelope_response = envelope; - response = envelope->Body->any->data; - LASSO_WSF_PROFILE(service)->response = LASSO_NODE(response); + if (! LASSO_IS_DST_MODIFY_RESPONSE(service->parent.response)) { + rc = LASSO_PROFILE_ERROR_MISSING_RESPONSE; + } - return 0; -} - -/** - * lasso_data_service_get_resource_offering: - * @service: a #LassoDataService - * - * Gets the #LassoDiscoResourceOffering of the @service. - * - * Return value: the #LassoDiscoResourceOffering associated to service. - **/ -LassoDiscoResourceOffering* -lasso_data_service_get_resource_offering(LassoDataService *service) -{ - return g_object_ref(service->private_data->offering); + return rc; } @@ -899,20 +891,6 @@ lasso_data_service_get_resource_offering(LassoDataService *service) static LassoNodeClass *parent_class = NULL; -void -lasso_data_service_set_offering(LassoDataService *service, LassoDiscoResourceOffering *offering) -{ - service->private_data->offering = g_object_ref(offering); - if (offering->ResourceID != NULL) { - service->resource_id = g_object_ref(offering->ResourceID); - } - if (offering->EncryptedResourceID != NULL) { - service->encrypted_resource_id = g_object_ref(offering->EncryptedResourceID); - } - service->provider_id = g_strdup(offering->ServiceInstance->ProviderID); - service->abstract_description = g_strdup(offering->Abstract); -} - static void register_xpath_namespace(gchar *prefix, gchar *href, xmlXPathContext *xpathCtx) { @@ -932,6 +910,119 @@ lasso_register_idwsf_xpath_namespaces(xmlXPathContext *xpathCtx) (GHFunc)register_xpath_namespace, xpathCtx); } +static gint +lasso_data_service_apply_query(LassoDataService *service, LassoDstQueryResponse *query_response, xmlXPathContext *xpathCtx, LassoDstQueryItem *item) +{ + gint rc = 0; + xmlXPathObject *xpathObj = NULL; + gint xpath_error_code = 0; + + lasso_bad_param(DATA_SERVICE, service); + lasso_bad_param(DST_QUERY_RESPONSE, query_response); + lasso_bad_param(DST_QUERY_ITEM, item); + + if (! item->Select) { + lasso_wsf_profile_helper_set_status(query_response, LASSO_DST_STATUS_CODE_FAILED); + lasso_wsf_profile_helper_set_status(query_response->Status, LASSO_DST_STATUS_CODE_MISSING_SELECT); + goto_cleanup_with_rc(1); + } + + if (lasso_eval_xpath_expression(xpathCtx, item->Select, &xpathObj, &xpath_error_code)) { + LassoDstData *data = NULL; + + /* Found zero or more node answers */ + if (xpathObj && xpathObj->type == XPATH_NODESET){ + int i = 0; + + if (xpathObj->nodesetval && xpathObj->nodesetval->nodeNr) { + data = lasso_dst_data_new(); + } + + for (i = 0; xpathObj->nodesetval && i < xpathObj->nodesetval->nodeNr; + i++) { + lasso_list_add_xml_node(data->any, + xpathObj->nodesetval->nodeTab[i]); + } + /* Found other kind of answers, convert to string */ + } else { + xmlChar *str; + + data = lasso_dst_data_new(); + str = xmlXPathCastToString(xpathObj); + lasso_list_add_xml_node(data->any, xmlNewText(str)); + lasso_release_xml_string(str); + } + if (data) { + lasso_assign_string(data->itemIDRef, item->itemID); + lasso_list_add_gobject(query_response->Data, data); + } + lasso_release_gobject(data); + } else { + char *code = g_strdup_printf("LIBXML_XPATH_ERROR_%d", xpath_error_code); + + lasso_wsf_profile_helper_set_status(query_response, LASSO_DST_STATUS_CODE_FAILED); + lasso_wsf_profile_helper_set_status(query_response->Status, LASSO_DST_STATUS_CODE_INVALID_SELECT); + lasso_wsf_profile_helper_set_status(query_response->Status->Status, code); + lasso_release_string(code); + goto_cleanup_with_rc(1); + } + +cleanup: + lasso_release_xpath_object(xpathObj); + return rc; +} + +G_GNUC_UNUSED static gint +lasso_data_service_apply_queries(LassoDataService *service, LassoDstQueryResponse *query_response, xmlNode *data, GList *queries) +{ + gint rc = 0; + LassoWsfProfile *wsf_profile = NULL; + xmlDoc *doc = NULL; + xmlXPathContext *xpathCtx = NULL; + + lasso_bad_param(DATA_SERVICE, service); + g_return_val_if_fail(service->private_data, LASSO_PARAM_ERROR_NON_INITIALIZED_OBJECT); + wsf_profile = &service->parent; + + /* 1. Check query */ + if (queries && queries->next) { + GList *q = queries; + while (q) { + if (! LASSO_IS_DST_QUERY_ITEM(q->data) || ! + LASSO_DST_QUERY_ITEM(q->data)->itemID) { + lasso_wsf_profile_helper_set_status(query_response, + LASSO_DST_STATUS_CODE_FAILED); + lasso_wsf_profile_helper_set_status(query_response->Status, + "itemID expected"); + goto_cleanup_with_rc(LASSO_DST_ERROR_QUERY_FAILED); + } + q = g_list_next(q); + } + } + + /* 1. Setup workbench */ + doc = xmlNewDoc((xmlChar*)"1.0"); + xmlDocSetRootElement(doc, data); + xpathCtx = xmlXPathNewContext(doc); + lasso_register_idwsf_xpath_namespaces(xpathCtx); + + lasso_foreach (queries, queries) { + LassoDstQueryItem *item = queries->data; + + goto_cleanup_if_fail_with_rc(lasso_data_service_apply_query(service, query_response, + xpathCtx, item) == 0, query_response->Data ? + LASSO_DST_ERROR_QUERY_PARTIALLY_FAILED : + LASSO_DST_ERROR_QUERY_FAILED); + } + +cleanup: + xmlUnlinkNode(service->private_data->resource_data); + xmlSetTreeDoc(service->private_data->resource_data, NULL); + lasso_release_xpath_context(xpathCtx); + lasso_release_doc(doc); + + return rc; +} /*****************************************************************************/ /* overrided parent class methods */ @@ -942,11 +1033,9 @@ dispose(GObject *object) { LassoDataService *service = LASSO_DATA_SERVICE(object); - if (service->private_data->dispose_has_run == TRUE) - return; - g_free(service->provider_id); - service->provider_id = NULL; - service->private_data->dispose_has_run = TRUE; + lasso_release_xml_node(service->private_data->resource_data); + lasso_release_gobject(service->private_data->ResourceID); + lasso_release_gobject(service->private_data->EncryptedResourceID); G_OBJECT_CLASS(parent_class)->dispose(object); } @@ -954,13 +1043,8 @@ dispose(GObject *object) static void finalize(GObject *object) { - LassoDataService *service = LASSO_DATA_SERVICE(object); - if (service->private_data->offering) { - lasso_node_destroy(LASSO_NODE(service->private_data->offering)); - service->private_data->offering = NULL; - } - g_free(service->private_data); - service->private_data = NULL; + g_free(((LassoDataService*)object)->private_data); + G_OBJECT_CLASS(parent_class)->finalize(object); } @@ -972,9 +1056,7 @@ finalize(GObject *object) static void instance_init(LassoDataService *service) { - service->resource_data = NULL; service->private_data = g_new0(LassoDataServicePrivate, 1); - service->private_data->fault = NULL; } static void @@ -1054,7 +1136,7 @@ lasso_data_service_new_full(LassoServer *server, LassoDiscoResourceOffering *off return NULL; } - lasso_data_service_set_offering(LASSO_DATA_SERVICE(service), offering); + lasso_wsf_profile_set_resource_offering(&service->parent, offering); return service; } diff --git a/lasso/id-wsf/data_service.h b/lasso/id-wsf/data_service.h index 4d6dfadd..4097ca1d 100644 --- a/lasso/id-wsf/data_service.h +++ b/lasso/id-wsf/data_service.h @@ -59,14 +59,6 @@ typedef struct _LassoDataServicePrivate LassoDataServicePrivate; struct _LassoDataService { LassoWsfProfile parent; - /*< public >*/ - LassoDiscoResourceID *resource_id; - LassoDiscoEncryptedResourceID *encrypted_resource_id; - xmlNode *resource_data; - - gchar *provider_id; - gchar *abstract_description; - /*< private >*/ LassoDataServicePrivate *private_data; }; @@ -86,7 +78,7 @@ LASSO_EXPORT LassoDataService* lasso_data_service_new_full(LassoServer *server, LASSO_EXPORT gint lasso_data_service_init_query(LassoDataService *service, const char *select, const char *item_id, const char *security_mech_id); -LASSO_EXPORT LassoDstQueryItem* lasso_data_service_add_query_item(LassoDataService *service, +LASSO_EXPORT gint lasso_data_service_add_query_item(LassoDataService *service, const char *select, const char *item_id); LASSO_EXPORT gint lasso_data_service_process_query_msg(LassoDataService *service, @@ -99,17 +91,22 @@ LASSO_EXPORT gint lasso_data_service_build_response_msg(LassoDataService *servic LASSO_EXPORT gint lasso_data_service_process_query_response_msg(LassoDataService *service, const char *message); -LASSO_EXPORT xmlNode* lasso_data_service_get_answer(LassoDataService *service, - const char *select); +LASSO_EXPORT gint lasso_data_service_get_answer(LassoDataService *service, + xmlNode **output); + +LASSO_EXPORT gint lasso_data_service_get_answers(LassoDataService *service, GList **output); -LASSO_EXPORT xmlNode* lasso_data_service_get_answer_for_item_id(LassoDataService *service, - const char *item_id); +LASSO_EXPORT gint lasso_data_service_get_answers_by_select(LassoDataService *service, + const char *select, GList OFTYPE(xmlNode) **output); -LASSO_EXPORT gint lasso_data_service_init_modify(LassoDataService *service, - const gchar *select, xmlNode *newData); +LASSO_EXPORT gint lasso_data_service_get_answers_by_item_id(LassoDataService *service, + const char *item_id, GList OFTYPE(xmlNode) **output); -LASSO_EXPORT LassoDstModification* lasso_data_service_add_modification( - LassoDataService *service, const gchar *select); +LASSO_EXPORT gint lasso_data_service_init_modify(LassoDataService *service); + +LASSO_EXPORT gint lasso_data_service_add_modification(LassoDataService *service, + const gchar *select, xmlNode *xmlData, gboolean overrideAllowed, + time_t *notChangedSince, LassoDstModification **output); LASSO_EXPORT gint lasso_data_service_process_modify_msg(LassoDataService *service, const gchar *soap_msg, const gchar *security_mech_id); @@ -117,9 +114,6 @@ LASSO_EXPORT gint lasso_data_service_process_modify_msg(LassoDataService *servic LASSO_EXPORT gint lasso_data_service_process_modify_response_msg(LassoDataService *service, const gchar *soap_msg); -LASSO_EXPORT gboolean lasso_data_service_need_redirect_user(LassoDataService *service, - const char *redirectUrl); - LASSO_EXPORT gchar* lasso_data_service_get_redirect_request_url(LassoDataService *service); LASSO_EXPORT LassoDiscoResourceOffering* lasso_data_service_get_resource_offering( diff --git a/lasso/id-wsf/data_service_private.h b/lasso/id-wsf/data_service_private.h deleted file mode 100644 index 8514b69f..00000000 --- a/lasso/id-wsf/data_service_private.h +++ /dev/null @@ -1,42 +0,0 @@ -/* $Id$ - * - * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __LASSO_DATA_SERVICE_PRIVATE_H__ -#define __LASSO_DATA_SERVICE_PRIVATE_H__ - -#ifdef __cplusplus -extern "C" { - -#endif /* __cplusplus */ - -void lasso_data_service_set_offering(LassoDataService *service, - LassoDiscoResourceOffering *offering); - -gint lasso_data_service_add_credential(LassoDataService *service, LassoSamlAssertion *assertion); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __LASSO_DATA_SERVICE_PRIVATE_H__ */ diff --git a/lasso/id-wsf/discovery.c b/lasso/id-wsf/discovery.c index 5aa795d4..e044c9cb 100644 --- a/lasso/id-wsf/discovery.c +++ b/lasso/id-wsf/discovery.c @@ -55,6 +55,7 @@ * * lasso_discovery_process_query_response_msg(discovery, soap_answer); * + * // get an object to access the first service returned, or NULL if an error happened * service = lasso_discovery_get_service(discovery); * </programlisting> * </informalexample> @@ -67,25 +68,22 @@ #include <xmlsec/xmltree.h> -#include <lasso/utils.h> -#include <lasso/xml/soap_binding_correlation.h> -#include <lasso/xml/saml_assertion.h> -#include <lasso/xml/saml_attribute.h> -#include <lasso/xml/saml_attribute_value.h> -#include <lasso/xml/disco_modify.h> -#include <lasso/xml/saml_assertion.h> - -#include <lasso/id-ff/server.h> -#include <lasso/id-ff/provider.h> -#include <lasso/id-ff/providerprivate.h> -#include <lasso/id-ff/sessionprivate.h> - -#include <lasso/id-wsf/discovery.h> -#include <lasso/id-wsf/identity.h> -#include <lasso/id-wsf/data_service.h> -#include <lasso/id-wsf/personal_profile_service.h> -#include <lasso/id-wsf/wsf_profile_private.h> -#include <lasso/id-wsf/utils.h> +#include "../utils.h" +#include "../xml/soap_binding_correlation.h" +#include "../xml/saml_assertion.h" +#include "../xml/saml_attribute.h" +#include "../xml/saml_attribute_value.h" +#include "../xml/disco_modify.h" +#include "../xml/saml_assertion.h" + +#include "../id-ff/server.h" +#include "../id-ff/provider.h" +#include "../id-ff/providerprivate.h" +#include "../id-ff/sessionprivate.h" + +#include "id_wsf.h" +#include "wsf_profile_private.h" +#include "utils.h" #include "../utils.h" struct _LassoDiscoveryPrivate @@ -95,6 +93,16 @@ struct _LassoDiscoveryPrivate char *security_mech_id; }; +#define assign_resource_id(from,to) \ + if ((from)->ResourceID) {\ + lasso_assign_gobject((to)->ResourceID, (from)->ResourceID); \ + } else if ((from)->EncryptedResourceID) {\ + lasso_assign_gobject((to)->EncryptedResourceID, (from)->EncryptedResourceID); \ + } else { \ + rc = LASSO_WSF_PROFILE_ERROR_MISSING_RESOURCE_ID;\ + goto_cleanup_if_fail(0); \ + } + /*****************************************************************************/ /* static methods/functions */ /*****************************************************************************/ @@ -107,89 +115,14 @@ static void remove_registry(gchar const *service_type); static void set_registry(gchar const *service_type, LassoWsfProfileConstructor constructor); static LassoDsKeyInfo* lasso_discovery_build_key_info_node(LassoDiscovery *discovery, const gchar *providerID); - -/* Needs REVIEW */ -static gchar* -lasso_discovery_build_credential(LassoDiscovery *discovery, G_GNUC_UNUSED const gchar *providerId) -{ - /* XXX: providerId parameter is never used */ - - LassoWsfProfile *profile = NULL; - LassoSoapHeader *header = NULL; - LassoSoapBindingProvider *provider = NULL; - LassoDiscoQueryResponse *response = NULL; - LassoDiscoCredentials *credentials = NULL; - LassoSamlAssertion *assertion = NULL; - LassoSamlAuthenticationStatement *authentication_statement = NULL; - LassoSamlSubject *subject = NULL; - LassoSamlNameIdentifier *name_identifier = NULL; - LassoSamlSubjectConfirmation *subject_confirmation = NULL; - LassoDsKeyInfo *key_info = NULL; - GList *iter = NULL; - LassoProvider *our_provider = - LASSO_PROVIDER(LASSO_WSF_PROFILE(discovery)->server); - - g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), NULL); - - /* Init assertion informations */ - assertion = lasso_saml_assertion_new(); - assertion->AssertionID = lasso_build_unique_id(32); - assertion->MajorVersion = LASSO_SAML_MAJOR_VERSION_N; - assertion->MinorVersion = LASSO_SAML_MINOR_VERSION_N; - assertion->IssueInstant = lasso_get_current_time(); - assertion->Issuer = g_strdup(our_provider->ProviderID); - - /* Add AuthenticationStatement */ - authentication_statement = LASSO_SAML_AUTHENTICATION_STATEMENT( - lasso_saml_authentication_statement_new()); - authentication_statement->AuthenticationInstant = lasso_get_current_time(); - - subject = LASSO_SAML_SUBJECT(lasso_saml_subject_new()); - - /* NameIdentifier */ - name_identifier = lasso_saml_name_identifier_new(); - name_identifier->NameQualifier = g_strdup( - our_provider->ProviderID); - header = LASSO_WSF_PROFILE(discovery)->soap_envelope_request->Header; - iter = header->Other; - while (iter) { - if (LASSO_IS_SOAP_BINDING_PROVIDER(iter->data) == TRUE) { - provider = LASSO_SOAP_BINDING_PROVIDER(iter->data); - break; - } - } - if (provider != NULL) { - name_identifier->Format = g_strdup(LASSO_LIB_NAME_IDENTIFIER_FORMAT_ENTITYID); - name_identifier->content = g_strdup(provider->providerID); - } else { - name_identifier->Format = g_strdup(LASSO_LIB_NAME_IDENTIFIER_FORMAT_FEDERATED); - } - subject->NameIdentifier = name_identifier; - - /* SubjectConfirmation */ - subject_confirmation = lasso_saml_subject_confirmation_new(); - lasso_list_add_string(subject_confirmation->ConfirmationMethod, - g_strdup(LASSO_SAML_CONFIRMATION_METHOD_HOLDER_OF_KEY)); - - /* Add public key value in credential */ - key_info = lasso_discovery_build_key_info_node(discovery, provider->providerID); - if (key_info != NULL) { - subject_confirmation->KeyInfo = key_info; - } - subject->SubjectConfirmation = subject_confirmation; - - /* Add the subject in the authentication statement */ - LASSO_SAML_SUBJECT_STATEMENT_ABSTRACT(authentication_statement)->Subject = subject; - assertion->AuthenticationStatement = authentication_statement; - - /* Add credential to disco:QueryResponse */ - response = LASSO_DISCO_QUERY_RESPONSE(profile->response); - credentials = lasso_disco_credentials_new(); - lasso_list_add_new_gobject(credentials->any, assertion); - response->Credentials = credentials; - - return g_strdup(assertion->AssertionID); -} +static LassoDiscoResourceOffering* lasso_discovery_get_resource_offering_auto( + LassoDiscovery *discovery, const gchar *service_type); +static gint lasso_discovery_init_resource_offering(LassoDiscovery *discovery, + const gchar *security_mech_id, LassoDiscoResourceOffering **output_offering); +static gint lasso_discovery_process_modify_msg(LassoDiscovery *discovery); +static gint lasso_discovery_process_query_msg(LassoDiscovery *discovery); +static gint lasso_discovery_build_query_response_msg(LassoDiscovery *discovery); +static gint lasso_discovery_build_modify_response_msg(LassoDiscovery *discovery); /** * lasso_discovery_add_insert_entry: @@ -197,13 +130,13 @@ lasso_discovery_build_credential(LassoDiscovery *discovery, G_GNUC_UNUSED const * @serviceInstance: an optional #LassoDiscoServiceInstance object * @resourceID: the new #LassoDiscoResourceID used to create the #LassoDiscoResrouceOffering * - * Add an InsertEntry containing a DiscoResourceOffering for this resrouceId, - * initialize the DiscoResourceOffering using serviceInstance. + * Add an #LassoDiscoInsertEntry containing a new #LassoDiscoResourceOffering, and initialize the + * #LassoDiscoResourceOffering using the #LassoDiscoServiceInstance and #LassoDiscoResourceId + * object. * - * Return value: the newly created #LassoDiscoInsertEntry or NULL if some - * preconditions failed. + * Return value: the newly created #LassoDiscoInsertEntry or NULL if some preconditions failed. **/ -LassoDiscoInsertEntry* +gint lasso_discovery_add_insert_entry(LassoDiscovery *discovery, LassoDiscoServiceInstance *serviceInstance, LassoDiscoResourceID *resourceId) @@ -211,22 +144,23 @@ lasso_discovery_add_insert_entry(LassoDiscovery *discovery, LassoDiscoModify *modify = NULL; LassoDiscoInsertEntry *insertEntry = NULL; LassoDiscoResourceOffering *resourceOffering = NULL; + int rc = 0; - g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), NULL); - g_return_val_if_fail(LASSO_IS_DISCO_SERVICE_INSTANCE(serviceInstance), NULL); - g_return_val_if_fail(LASSO_IS_DISCO_RESOURCE_ID(resourceId), NULL); - - modify = LASSO_DISCO_MODIFY(LASSO_WSF_PROFILE(discovery)->request); + lasso_bad_param(DISCOVERY, discovery); + lasso_bad_param(DISCO_SERVICE_INSTANCE, serviceInstance); + lasso_bad_param(DISCO_RESOURCE_ID, resourceId); + g_return_val_if_fail(LASSO_IS_DISCO_MODIFY(LASSO_WSF_PROFILE(discovery)->request), LASSO_PARAM_ERROR_NON_INITIALIZED_OBJECT); - /* ResourceOffering elements being inserted MUST NOT contain entryID attributes. */ + lasso_extract_node_or_fail(modify, LASSO_WSF_PROFILE(discovery)->request, DISCO_MODIFY, + LASSO_PROFILE_ERROR_MISSING_REQUEST); resourceOffering = lasso_disco_resource_offering_new(serviceInstance); lasso_assign_gobject(resourceOffering->ResourceID, resourceId); - insertEntry = lasso_disco_insert_entry_new(resourceOffering); + lasso_list_add_gobject(modify->InsertEntry, insertEntry); - lasso_list_add_new_gobject(modify->InsertEntry, insertEntry); - - return insertEntry; +cleanup: + lasso_release_gobject(resourceOffering); + return rc; } /** @@ -238,23 +172,24 @@ lasso_discovery_add_insert_entry(LassoDiscovery *discovery, * to remove the resource offering identified by entryID (returned in the * response to a Modify/InsertEntry message). * - * Return value: 0 + * Return value: 0 if successful, an error code otherwise. **/ gint lasso_discovery_add_remove_entry(LassoDiscovery *discovery, const gchar *entryID) { LassoDiscoModify *modify = NULL; + gint rc = 0; - g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(entryID != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - - modify = LASSO_DISCO_MODIFY(LASSO_WSF_PROFILE(discovery)->request); + lasso_bad_param(DISCOVERY, discovery); + lasso_null_param(entryID); + lasso_extract_node_or_fail(modify, LASSO_WSF_PROFILE(discovery)->request, DISCO_MODIFY, + LASSO_PROFILE_ERROR_MISSING_REQUEST); - /* add RemoveEntry */ lasso_list_add_new_gobject(modify->RemoveEntry, lasso_disco_remove_entry_new(entryID)); - return 0; +cleanup: + return rc; } /** @@ -265,163 +200,39 @@ lasso_discovery_add_remove_entry(LassoDiscovery *discovery, * * Adds a request for service of @service_type to the disco:Query being built. * - * Return value: a newly created #LassoDiscoRequestedServiceType with the - * request. Note that it is internally allocated and shouldn't be freed - * by the caller. + * Return value: 0 if successful **/ -LassoDiscoRequestedServiceType* +gint lasso_discovery_add_requested_service_type(LassoDiscovery *discovery, const gchar *service_type, const gchar *option) { - LassoWsfProfile *profile = NULL; - LassoDiscoQuery *query = NULL; LassoDiscoRequestedServiceType *rst = NULL; LassoDiscoOptions *opts = NULL; + LassoDiscoQuery *query = NULL; + gint rc = 0; - g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), NULL); - g_return_val_if_fail(service_type != NULL, NULL); - /* "option" parameter is optional */ - - profile = LASSO_WSF_PROFILE(discovery); - - if (! LASSO_IS_DISCO_QUERY(profile->request)) { - return NULL; - } - query = LASSO_DISCO_QUERY(profile->request); + lasso_bad_param(DISCOVERY, discovery); + lasso_null_param(service_type); + lasso_extract_node_or_fail(query, LASSO_WSF_PROFILE(discovery)->request, DISCO_QUERY, + LASSO_PARAM_ERROR_NON_INITIALIZED_OBJECT); rst = lasso_disco_requested_service_type_new(service_type); - - /* optionals data */ if (option != NULL) { opts = lasso_disco_options_new(); - lasso_list_add(opts->Option, (gpointer)option); - rst->Options = opts; + lasso_list_add_string(opts->Option, option); + lasso_assign_new_gobject(rst->Options, opts); } - - /* add RequestedServiceType */ lasso_list_add_new_gobject(query->RequestedServiceType, rst); - return rst; -} - -/** - * lasso_discovery_init_modify: - * - * @Deprecated: Since 2.2.1, use lasso_discovery_init_insert() instead. - **/ -gint -lasso_discovery_init_modify(G_GNUC_UNUSED LassoDiscovery *discovery, - G_GNUC_UNUSED LassoDiscoResourceOffering *resourceOffering, - G_GNUC_UNUSED LassoDiscoDescription *description) -{ - return 0; -} - -static LassoDiscoResourceOffering* -lasso_discovery_get_resource_offering_auto(LassoDiscovery *discovery, const gchar *service_type) -{ - LassoWsfProfile *profile = LASSO_WSF_PROFILE(discovery); - LassoDiscoResourceOffering *resource_offering = NULL; - LassoSession *session = NULL; - GList *assertions = NULL; - LassoSamlAssertion *assertion = NULL; - LassoSamlAttribute *attribute = NULL; - LassoSamlAttributeValue *attribute_value = NULL; - LassoDiscoResourceOffering *offering = NULL; - GList *iter = NULL; - GList *iter2 = NULL; - GList *iter3 = NULL; - GList *iter4 = NULL; - - if (profile->session == NULL) { - return NULL; - } - - session = profile->session; - assertions = lasso_session_get_assertions(session, NULL); - for (iter = assertions; iter != NULL; iter = g_list_next(iter)) { - if (! LASSO_IS_SAML_ASSERTION(iter->data)) { - continue; - } - assertion = LASSO_SAML_ASSERTION(iter->data); - if (assertion->AttributeStatement == NULL) { - continue; - } - for (iter2 = assertion->AttributeStatement->Attribute; iter2 != NULL; - iter2 = g_list_next(iter2)) { - if (! LASSO_IS_SAML_ATTRIBUTE(iter2->data)) { - continue; - } - attribute = LASSO_SAML_ATTRIBUTE(iter2->data); - if (strcmp(attribute->attributeName, "DiscoveryResourceOffering") != 0) { - continue; - } - for (iter3 = attribute->AttributeValue; iter3 != NULL; - iter3 = g_list_next(iter3)) { - if (! LASSO_IS_SAML_ATTRIBUTE_VALUE(iter3->data)) { - continue; - } - attribute_value = LASSO_SAML_ATTRIBUTE_VALUE(iter3->data); - for (iter4 = attribute_value->any; iter4 != NULL; - iter4 = g_list_next(iter4)) { - if (! LASSO_IS_DISCO_RESOURCE_OFFERING(iter4->data)) { - continue; - } - offering = LASSO_DISCO_RESOURCE_OFFERING(iter4->data); - if (offering->ServiceInstance == NULL) { - continue; - } - if (strcmp(offering->ServiceInstance->ServiceType, - service_type) == 0) { - resource_offering = offering; - goto end; - } - } - } - } - } - -end: - g_list_free(assertions); - return resource_offering; +cleanup: + return rc; } /** - * lasso_discovery_get_description_auto: - * - * - * - * Return value: internally allocated, don't free - **/ -LassoDiscoDescription* -lasso_discovery_get_description_auto(const LassoDiscoResourceOffering *offering, - const gchar *security_mech_id) -{ - g_return_val_if_fail(LASSO_IS_DISCO_RESOURCE_OFFERING(offering), NULL); - g_return_val_if_fail(security_mech_id != NULL, NULL); - - if (offering->ServiceInstance == NULL) { - return NULL; - } - - return lasso_wsf_profile_get_description_auto(offering->ServiceInstance, security_mech_id); -} - -#define assign_resource_id(from,to) \ - if ((from)->ResourceID) {\ - lasso_assign_gobject((to)->ResourceID, (from)->ResourceID); \ - } else if ((from)->EncryptedResourceID) {\ - lasso_assign_gobject((to)->EncryptedResourceID, (from)->EncryptedResourceID); \ - } else { \ - rc = LASSO_WSF_PROFILE_ERROR_MISSING_RESOURCE_ID;\ - } - - - -/** * lasso_discovery_init_query * @discovery: a #LassoDiscovery + * @security_mech_id: identifier of a wished security mechanism, or NULL if any is ok * * Initializes a disco:Query message. * @@ -433,183 +244,95 @@ lasso_discovery_init_query(LassoDiscovery *discovery, const gchar *security_mech LassoWsfProfile *profile = NULL; LassoDiscoQuery *query = NULL; LassoDiscoResourceOffering *offering = NULL; - const LassoDiscoDescription *description = NULL; gint rc = 0; - g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + lasso_bad_param(DISCOVERY, discovery); - profile = LASSO_WSF_PROFILE(discovery); + profile = &discovery->parent; + /* 1. Get an offering */ + rc = lasso_discovery_init_resource_offering(discovery, security_mech_id, &offering); + goto_cleanup_if_fail(! rc); + /* 2. Create SOAP envelope and set profile->request */ query = lasso_disco_query_new(); - /* FIXME: we should not get it automatically, - * we should get it from on one hand, and setup the discovery proxy - * object with get getted resource offering. get discovery service - * resource id from principal assertion */ - offering = lasso_discovery_get_resource_offering_auto(discovery, LASSO_DISCO_HREF); - goto_cleanup_if_fail_with_rc(LASSO_IS_DISCO_RESOURCE_OFFERING(offering), - LASSO_PROFILE_ERROR_MISSING_RESOURCE_OFFERING); - lasso_wsf_profile_set_resource_offering(&discovery->parent, offering); - rc = lasso_wsf_profile_set_security_mech_id(&discovery->parent, security_mech_id); - if (rc) - goto cleanup; - /* Create SOAP envelope and set profile->request */ lasso_wsf_profile_init_soap_request(profile, LASSO_NODE(query)); assign_resource_id(offering, query); - description = lasso_wsf_profile_get_description(&discovery->parent); - if (description->Endpoint != NULL) { - lasso_assign_string(profile->msg_url, description->Endpoint); - } else { - rc = LASSO_WSF_PROFILE_ERROR_MISSING_ENDPOINT; - } cleanup: lasso_release_gobject(query); return rc; } /** - * lasso_discovery_init_insert + * lasso_discovery_init_modify: * @discovery: a #LassoDiscovery - * @new_offering: the new service offered * @security_mech_id: the security mechanism identifier * * Initializes a disco Modify/InsertEntry * - * Return value: 0 on success; or a negative value otherwise. + * Return value: 0 on success; an error code otherwise. **/ gint -lasso_discovery_init_insert(LassoDiscovery *discovery, LassoDiscoResourceOffering *new_offering, +lasso_discovery_init_modify(LassoDiscovery *discovery, const char *security_mech_id) { LassoWsfProfile *profile = NULL; LassoDiscoModify *modify = NULL; LassoDiscoResourceOffering *offering = NULL; - LassoDiscoDescription *description = NULL; - gint rc = 0; - - g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(LASSO_IS_DISCO_RESOURCE_OFFERING(new_offering), - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - - profile = LASSO_WSF_PROFILE(discovery); - modify = lasso_disco_modify_new(); - lasso_wsf_profile_init_soap_request(profile, LASSO_NODE(modify)); - - /* get discovery service resource id from principal assertion */ - offering = lasso_discovery_get_resource_offering_auto(discovery, LASSO_DISCO_HREF); - if (! LASSO_IS_DISCO_RESOURCE_OFFERING(offering)) { - return LASSO_PROFILE_ERROR_MISSING_RESOURCE_OFFERING; - } - lasso_wsf_profile_set_resource_offering(&discovery->parent, offering); - if (security_mech_id) { - description = lasso_discovery_get_description_auto(offering, security_mech_id); - } else if (offering->ServiceInstance && offering->ServiceInstance->Description) { - description = LASSO_DISCO_DESCRIPTION(offering->ServiceInstance->Description->data); - } - if (! LASSO_IS_DISCO_DESCRIPTION(description)) { - return LASSO_PROFILE_ERROR_MISSING_SERVICE_DESCRIPTION; - } - lasso_wsf_profile_set_description(profile, description); - assign_resource_id(offering, modify); - lasso_node_destroy(LASSO_NODE(offering)); - lasso_list_add_new_gobject(modify->InsertEntry, lasso_disco_insert_entry_new(new_offering)); - if (description->Endpoint != NULL) { - profile->msg_url = g_strdup(description->Endpoint); - } /* TODO: else, description->WsdlURI, get endpoint automatically */ - - return rc; -} - - -/** - * lasso_discovery_init_remove - * @discovery: a #LassoDiscovery - * @entry_id: entry id of the resource offering to remove - * - * Initializes a disco Modify/RemoveEntry - * - * Return value: 0 on success; or a negative value otherwise. - **/ -gint -lasso_discovery_init_remove(LassoDiscovery *discovery, const char *entry_id) -{ - LassoWsfProfile *profile = NULL; - LassoDiscoModify *modify = NULL; - LassoDiscoResourceOffering *offering = NULL; - LassoDiscoDescription *description = NULL; gint rc = 0; - g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + lasso_bad_param(DISCOVERY, discovery); - profile = LASSO_WSF_PROFILE(discovery); + profile = &discovery->parent; + /* 1. Get an offering */ + rc = lasso_discovery_init_resource_offering(discovery, security_mech_id, &offering); + goto_cleanup_if_fail (! rc); + /* 2. Set message content */ modify = lasso_disco_modify_new(); + assign_resource_id(offering, modify); lasso_wsf_profile_init_soap_request(profile, LASSO_NODE(modify)); - - /* get discovery service resource id from principal assertion */ - offering = lasso_discovery_get_resource_offering_auto(discovery, LASSO_DISCO_HREF); - if (! LASSO_IS_DISCO_RESOURCE_OFFERING(offering)) { - return LASSO_PROFILE_ERROR_MISSING_RESOURCE_OFFERING; - } - lasso_wsf_profile_set_resource_offering(&discovery->parent, offering); - - description = lasso_discovery_get_description_auto(offering, LASSO_SECURITY_MECH_NULL); - if (! LASSO_IS_DISCO_DESCRIPTION(description)) { - return LASSO_PROFILE_ERROR_MISSING_SERVICE_DESCRIPTION; - } - - /* TODO: EncryptedResourceID support */ - modify->ResourceID = g_object_ref(offering->ResourceID); - lasso_node_destroy(LASSO_NODE(offering)); - lasso_list_add_new_gobject(modify->RemoveEntry, lasso_disco_remove_entry_new(entry_id)); - if (description->Endpoint != NULL) { - profile->msg_url = g_strdup(description->Endpoint); - } /* TODO: else, description->WsdlURI, get endpoint automatically */ - +cleanup: + lasso_release_gobject(modify); return rc; } /** - * lasso_discovery_process_modify_msg: - * @discovery: a #LassoDiscovery - * @message: the disco:Modify SOAP message + * lasso_discovery_process_request_msg: + * @discovery: a #LassoDiscovery object + * @message: a serialized SOAP message + * @security_mech_id: the security mech id to use for validating authorizations * - * Processes a disco:Modify SOAP message. Rebuilds a request object from the - * message and extracts ResourceID. + * Process a received SOAP message for the discovery service. * - * Return value: 0 on success; or a negative value otherwise. - **/ + * Return value: 0 if successfull, an error code otherwise. + */ gint -lasso_discovery_process_modify_msg(LassoDiscovery *discovery, const gchar *message, - const gchar *security_mech_id) +lasso_discovery_process_request_msg(LassoDiscovery *discovery, const gchar *message, + const gchar *security_mech_id) { + gint rc = 0; LassoWsfProfile *profile = NULL; - LassoDiscoModify *request = NULL; - int res; g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(message != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + g_return_val_if_fail(message != NULL, LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); profile = LASSO_WSF_PROFILE(discovery); - - res = lasso_wsf_profile_process_soap_request_msg(profile, message, - LASSO_DISCO_HREF, security_mech_id); - if (res != 0) { - return res; + rc = lasso_wsf_profile_process_soap_request_msg(profile, message, + security_mech_id); + if (rc) { + return rc; } - - request = LASSO_DISCO_MODIFY(profile->request); - - if (request->ResourceID) { - discovery->resource_id = g_object_ref(request->ResourceID); - } else if (request->EncryptedResourceID) { - discovery->encrypted_resource_id = g_object_ref(request->EncryptedResourceID); + if (LASSO_IS_DISCO_MODIFY(profile->request)) { + return lasso_discovery_process_modify_msg(discovery); + } else if (LASSO_IS_DISCO_QUERY(profile->request)) { + return lasso_discovery_process_query_msg(discovery); + } else { + return LASSO_PROFILE_ERROR_INVALID_MSG; } - - return 0; + return rc; } - /** * lasso_discovery_build_modify_response_msg: * @discovery: a #LassoDiscovery @@ -622,12 +345,12 @@ lasso_discovery_process_modify_msg(LassoDiscovery *discovery, const gchar *messa * * Return value: 0 on success; or a negative value otherwise. **/ -gint +static gint lasso_discovery_build_modify_response_msg(LassoDiscovery *discovery) { /* FIXME: Check all error cases, set the right status code, and don't return without building a response, and - ensure atomicity, everythin fails or everythig succeed. */ + ensure atomicity, everything fails or everythig succeed. */ LassoWsfProfile *profile = NULL; LassoDiscoModify *request = NULL; @@ -647,10 +370,6 @@ lasso_discovery_build_modify_response_msg(LassoDiscovery *discovery) profile = LASSO_WSF_PROFILE(discovery); request = LASSO_DISCO_MODIFY(profile->request); - if (lasso_wsf_profile_get_fault(profile)) { - return lasso_wsf_profile_build_soap_response_msg(profile); - } - if (profile->identity == NULL) { return LASSO_PROFILE_ERROR_IDENTITY_NOT_FOUND; } @@ -717,8 +436,7 @@ lasso_discovery_build_modify_response_msg(LassoDiscovery *discovery) } if (res != 0) { - g_free(status->code); - status->code = g_strdup(LASSO_DISCO_STATUS_CODE_FAILED); + lasso_assign_string(status->code, LASSO_DISCO_STATUS_CODE_FAILED); } res2 = lasso_wsf_profile_build_soap_response_msg(profile); @@ -765,48 +483,43 @@ lasso_discovery_process_modify_response_msg(LassoDiscovery *discovery, const gch } /** - * lasso_discovery_process_query_msg: - * @discovery: a #LassoDiscovery - * @message: the disco:Query SOAP message + * lasso_discovery_build_response_msg: + * @discovery: a #LassoDiscovery object * - * Processes a disco:Query SOAP message. Rebuilds a request object from the - * message and extracts ResourceID. + * Execute needed action for the received request, and produce a response message. * - * Return value: 0 on success; or a negative value otherwise. - **/ + * If any critical error occur, it tries to produce a SOAP fault. + * + * Return value: 0 on success; or an error code otherwise. + */ gint -lasso_discovery_process_query_msg(LassoDiscovery *discovery, const gchar *message, - const char *security_mech_id) +lasso_discovery_build_response_msg(LassoDiscovery *discovery) { + gint rc = LASSO_PROFILE_ERROR_INVALID_MSG; LassoWsfProfile *profile = NULL; - LassoDiscoQuery *request = NULL; - LassoSoapEnvelope *envelope = NULL; g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(message != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); - - profile = LASSO_WSF_PROFILE(discovery); - - lasso_wsf_profile_process_soap_request_msg(profile, message, LASSO_DISCO_HREF, - security_mech_id); + profile = &discovery->parent; - envelope = profile->soap_envelope_response; - request = LASSO_DISCO_QUERY(profile->request); + if (G_IS_OBJECT(profile->request)) { - if (request->ResourceID) { - discovery->resource_id = g_object_ref(request->ResourceID); - } else if (request->EncryptedResourceID) { - discovery->encrypted_resource_id = g_object_ref(request->EncryptedResourceID); - } else { - return LASSO_ERROR_UNIMPLEMENTED; /* implied ? */ + if (LASSO_IS_DISCO_MODIFY(profile->request)) { + rc = lasso_discovery_build_modify_response_msg(discovery); + } + if (LASSO_IS_DISCO_QUERY(profile->request)) { + rc = lasso_discovery_build_query_response_msg(discovery); + } + } + if (rc < 0) { + rc = lasso_wsf_profile_build_soap_fault_response_msg(profile, rc); } + rc = lasso_wsf_profile_build_soap_response_msg(profile); - return 0; + return rc; } - /** - * lasso_discovery_build_response_msg + * lasso_discovery_build_query_response_msg * @discovery: a #LassoDiscovery * * Builds a disco:QueryResponse message; answer to the disco:Query passed to @@ -817,8 +530,8 @@ lasso_discovery_process_query_msg(LassoDiscovery *discovery, const gchar *messag * * Return value: 0 on success; or a negative value otherwise. **/ -gint -lasso_discovery_build_response_msg(LassoDiscovery *discovery) +static gint +lasso_discovery_build_query_response_msg(LassoDiscovery *discovery) { LassoWsfProfile *profile = NULL; LassoDiscoQuery *request = NULL; @@ -826,7 +539,6 @@ lasso_discovery_build_response_msg(LassoDiscovery *discovery) LassoSoapEnvelope *envelope = NULL; LassoSoapFault *fault = NULL; GList *offerings = NULL; - gchar *credentialRef; GList *iter = NULL; GList *iter2 = NULL; GList *iter3 = NULL; @@ -838,10 +550,6 @@ lasso_discovery_build_response_msg(LassoDiscovery *discovery) request = LASSO_DISCO_QUERY(profile->request); envelope = profile->soap_envelope_response; - if (lasso_wsf_profile_get_fault(profile)) { - return lasso_wsf_profile_build_soap_response_msg(profile); - } - if (profile->identity == NULL) { fault = lasso_soap_fault_new(); fault->faultcode = LASSO_SOAP_FAULT_CODE_SERVER; @@ -862,8 +570,6 @@ lasso_discovery_build_response_msg(LassoDiscovery *discovery) /* build response */ response = lasso_disco_query_response_new( lasso_utility_status_new(LASSO_DST_STATUS_CODE_OK)); - /* Keep refcount coherency */ - g_list_foreach(offerings, (GFunc)g_object_ref, NULL); response->ResourceOffering = offerings; profile->response = LASSO_NODE(response); lasso_list_add_gobject(envelope->Body->any, response); @@ -880,9 +586,9 @@ lasso_discovery_build_response_msg(LassoDiscovery *discovery) while (iter3) { if (lasso_security_mech_id_is_saml_authentication( iter3->data) == TRUE) { - credentialRef = lasso_discovery_build_credential( + gchar *credentialRef = lasso_discovery_build_credential( discovery, NULL); - lasso_list_add_new_gobject(description->CredentialRef, credentialRef); + lasso_list_add_new_string(description->CredentialRef, (void*)credentialRef); } iter3 = g_list_next(iter3); } @@ -962,7 +668,8 @@ cleanup: * @service_type: the requested service type * * After a disco:query message, creates a #LassoDataService instance for the - * requested @service_type. + * requested @service_type with the first resource offering found or the first resource offering + * matching the service type. * * Return value: a newly created #LassoDataService object; or NULL if an * error occured. @@ -971,44 +678,34 @@ LassoWsfProfile* lasso_discovery_get_service(LassoDiscovery *discovery, const char *service_type) { LassoWsfProfile *profile = NULL; - LassoDiscoQueryResponse *response; - GList *iter; + LassoDiscoQueryResponse *response = NULL; + GList *iter = NULL; LassoDiscoResourceOffering *offering = NULL; - LassoWsfProfile *service; + LassoWsfProfile *service = NULL; g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), NULL); + g_return_val_if_fail(LASSO_IS_DISCO_QUERY_RESPONSE(profile->response), NULL); profile = LASSO_WSF_PROFILE(discovery); - response = LASSO_DISCO_QUERY_RESPONSE(profile->response); - if (response == NULL) { - /* no response; probably called at wrong time */ - return NULL; - } iter = response->ResourceOffering; - if (iter == NULL) { - return NULL; /* resource not found */ - } - if (service_type == NULL) { - offering = iter->data; - } else { - while (iter) { - LassoDiscoResourceOffering *t = iter->data; - iter = g_list_next(iter); - if (t->ServiceInstance == NULL) - continue; - if (strcmp(t->ServiceInstance->ServiceType, service_type) == 0) { - offering = t; - break; - } + for (;iter; iter = g_list_next(iter)) { + LassoDiscoResourceOffering *t = iter->data; + + if (! LASSO_IS_DISCO_RESOURCE_OFFERING(t)) { + continue; } - if (offering == NULL) { - return NULL; /* resource not found */ + if (t->ServiceInstance == NULL) + continue; + if (service_type == NULL || strcmp(t->ServiceInstance->ServiceType, service_type) == 0) { + offering = t; + break; } } - service = lasso_discovery_build_wsf_profile(discovery, offering); - + if (offering) { + service = lasso_discovery_build_wsf_profile(discovery, offering); + } return service; } @@ -1030,19 +727,14 @@ lasso_discovery_get_services(LassoDiscovery *discovery) GList *iter; LassoDiscoResourceOffering *offering; LassoWsfProfile *service; - GList *services; + GList *services = NULL; g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), NULL); - profile = LASSO_WSF_PROFILE(discovery); + goto_cleanup_if_fail(LASSO_IS_DISCO_QUERY_RESPONSE(profile->response)); response = LASSO_DISCO_QUERY_RESPONSE(profile->response); iter = response->ResourceOffering; - if (iter == NULL) { - return NULL; /* resource not found */ - } - - services = NULL; while (iter) { offering = iter->data; iter = g_list_next(iter); @@ -1053,6 +745,7 @@ lasso_discovery_get_services(LassoDiscovery *discovery) lasso_list_add_new_gobject(services, service); } +cleanup: return services; } @@ -1107,6 +800,101 @@ lasso_discovery_unregister_constructor_for_service_type( remove_registry(service_type); } +/*****************************************************************************/ +/* private methods */ +/*****************************************************************************/ + +static LassoNodeClass *parent_class = NULL; +static GHashTable *registry = NULL; + +/** + * lasso_discovery_process_modify_msg: + * @discovery: a #LassoDiscovery + * @message: the disco:Modify SOAP message + * + * Processes a disco:Modify message. Rebuilds a request object from the + * message and extracts ResourceID. + * + * Return value: 0 on success; or a negative value otherwise. + **/ +static gint +lasso_discovery_process_modify_msg(LassoDiscovery *discovery) +{ + LassoWsfProfile *profile = NULL; + LassoDiscoModify *request = NULL; + gint rc = 0; + + g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(LASSO_IS_DISCO_MODIFY(LASSO_WSF_PROFILE(discovery)->request), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_WSF_PROFILE(discovery); + request = LASSO_DISCO_MODIFY(profile->request); + assign_resource_id(request, discovery); +cleanup: + return rc; +} + +/** + * lasso_discovery_process_query_msg: + * @discovery: a #LassoDiscovery + * + * Processes a disco:Query SOAP message. Rebuilds a request object from the + * message and extracts ResourceID. + * + * Return value: 0 on success; or a negative value otherwise. + **/ +static gint +lasso_discovery_process_query_msg(LassoDiscovery *discovery) +{ + LassoWsfProfile *profile = NULL; + LassoDiscoQuery *request = NULL; + gint rc = 0; + + g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + g_return_val_if_fail(LASSO_IS_DISCO_MODIFY(LASSO_WSF_PROFILE(discovery)->request), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + profile = LASSO_WSF_PROFILE(discovery); + request = LASSO_DISCO_QUERY(profile->request); + assign_resource_id(request, discovery); +cleanup: + return rc; +} + +/** + * lasso_discovery_init_resource_offering: + * @discovery: a #LassoDiscovery object + * @security_mech_id: a security mechanism string identifier + * @output_offering: a pointer to a variable to hold the found resource offering + * + * Return value: 0 if successfull, an error code otherwise. + **/ +static gint +lasso_discovery_init_resource_offering(LassoDiscovery *discovery, + const gchar *security_mech_id, LassoDiscoResourceOffering **output_offering) +{ + gint rc = 0; + LassoDiscoResourceOffering *offering = NULL; + + g_return_val_if_fail(LASSO_IS_DISCOVERY(discovery), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + if (! (offering = lasso_wsf_profile_get_resource_offering(&discovery->parent))) { + offering = lasso_discovery_get_resource_offering_auto(discovery, LASSO_DISCO_HREF); + lasso_wsf_profile_set_resource_offering(&discovery->parent, offering); + } + goto_cleanup_if_fail_with_rc(LASSO_IS_DISCO_RESOURCE_OFFERING(offering), + LASSO_PROFILE_ERROR_MISSING_RESOURCE_OFFERING); + rc = lasso_wsf_profile_set_security_mech_id(&discovery->parent, security_mech_id); + goto_cleanup_if_fail (! rc); + rc = lasso_wsf_profile_set_msg_url_from_description(&discovery->parent); + goto_cleanup_if_fail (! rc); +cleanup: + if (output_offering) { + *output_offering = offering; + } + return rc; +} /** * lasso_discovery_build_key_info_node: * @discovery: a #LassoDiscovery object @@ -1191,12 +979,180 @@ lasso_discovery_build_key_info_node(LassoDiscovery *discovery, const gchar *prov return key_info; } -/*****************************************************************************/ -/* private methods */ -/*****************************************************************************/ +static LassoDiscoResourceOffering* +lasso_discovery_get_resource_offering_auto(LassoDiscovery *discovery, const gchar *service_type) +{ + LassoWsfProfile *profile = LASSO_WSF_PROFILE(discovery); + LassoDiscoResourceOffering *resource_offering = NULL; + LassoSession *session = NULL; + GList *assertions = NULL; + LassoSamlAssertion *assertion = NULL; + LassoSamlAttribute *attribute = NULL; + LassoSamlAttributeValue *attribute_value = NULL; + LassoDiscoResourceOffering *offering = NULL; + GList *iter = NULL; + GList *iter2 = NULL; + GList *iter3 = NULL; + GList *iter4 = NULL; -static LassoNodeClass *parent_class = NULL; -static GHashTable *registry = NULL; + if (profile->session == NULL) { + return NULL; + } + + session = profile->session; + assertions = lasso_session_get_assertions(session, NULL); + for (iter = assertions; iter != NULL; iter = g_list_next(iter)) { + if (! LASSO_IS_SAML_ASSERTION(iter->data)) { + continue; + } + assertion = LASSO_SAML_ASSERTION(iter->data); + if (assertion->AttributeStatement == NULL) { + continue; + } + for (iter2 = assertion->AttributeStatement->Attribute; iter2 != NULL; + iter2 = g_list_next(iter2)) { + if (! LASSO_IS_SAML_ATTRIBUTE(iter2->data)) { + continue; + } + attribute = LASSO_SAML_ATTRIBUTE(iter2->data); + if (strcmp(attribute->attributeName, "DiscoveryResourceOffering") != 0) { + continue; + } + for (iter3 = attribute->AttributeValue; iter3 != NULL; + iter3 = g_list_next(iter3)) { + if (! LASSO_IS_SAML_ATTRIBUTE_VALUE(iter3->data)) { + continue; + } + attribute_value = LASSO_SAML_ATTRIBUTE_VALUE(iter3->data); + for (iter4 = attribute_value->any; iter4 != NULL; + iter4 = g_list_next(iter4)) { + if (! LASSO_IS_DISCO_RESOURCE_OFFERING(iter4->data)) { + continue; + } + offering = LASSO_DISCO_RESOURCE_OFFERING(iter4->data); + if (offering->ServiceInstance == NULL) { + continue; + } + if (strcmp(offering->ServiceInstance->ServiceType, + service_type) == 0) { + resource_offering = offering; + goto cleanup; + } + } + } + } + } + +cleanup: + g_list_free(assertions); + return resource_offering; +} + +/** + * lasso_discovery_build_credential: + * @discovery: an ID-WSF 1.0 discovery service object + * @providerId: the providerId for which the credential is build + * + * This function create a SAML assertion associating the public key of the given provider with its + * provider ID. This assertion will be signed by our own private key, creating a kind of + * certificate. + * + * Return value: the value of the attribute AssertionID of the created assertion. + */ +static gchar* +lasso_discovery_build_credential(LassoDiscovery *discovery, const gchar *providerId) +{ + LassoWsfProfile *profile = NULL; + LassoSoapHeader *header = NULL; + LassoSoapBindingProvider *provider = NULL; + LassoDiscoQueryResponse *response = NULL; + LassoDiscoCredentials *credentials = NULL; + LassoSamlAssertion *assertion = NULL; + LassoSamlAuthenticationStatement *authentication_statement = NULL; + LassoSamlSubject *subject = NULL; + LassoSamlNameIdentifier *name_identifier = NULL; + LassoSamlSubjectConfirmation *subject_confirmation = NULL; + LassoDsKeyInfo *key_info = NULL; + GList *iter = NULL; + LassoProvider *our_provider = + LASSO_PROVIDER(LASSO_WSF_PROFILE(discovery)->server); + gchar *assertionID = NULL; + + lasso_return_val_if_invalid_param(DISCOVERY, discovery, NULL); + + /* Init assertion informations */ + assertion = lasso_saml_assertion_new(); + assertion->AssertionID = lasso_build_unique_id(32); + assertion->MajorVersion = LASSO_SAML_MAJOR_VERSION_N; + assertion->MinorVersion = LASSO_SAML_MINOR_VERSION_N; + assertion->IssueInstant = lasso_get_current_time(); + lasso_assign_string(assertion->Issuer, our_provider->ProviderID); + + /* Add AuthenticationStatement */ + authentication_statement = LASSO_SAML_AUTHENTICATION_STATEMENT( + lasso_saml_authentication_statement_new()); + authentication_statement->AuthenticationInstant = lasso_get_current_time(); + + subject = LASSO_SAML_SUBJECT(lasso_saml_subject_new()); + + /* NameIdentifier */ + name_identifier = lasso_saml_name_identifier_new(); + name_identifier->NameQualifier = g_strdup( + our_provider->ProviderID); + + /* If no providerId was given use the one from the request */ + if (providerId == NULL) { + header = LASSO_WSF_PROFILE(discovery)->soap_envelope_request->Header; + iter = header->Other; + while (iter) { + if (LASSO_IS_SOAP_BINDING_PROVIDER(iter->data) == TRUE) { + provider = LASSO_SOAP_BINDING_PROVIDER(iter->data); + break; + } + } + providerId = provider->providerID; + } + + if (providerId != NULL) { + lasso_assign_string(name_identifier->Format, LASSO_LIB_NAME_IDENTIFIER_FORMAT_ENTITYID); + lasso_assign_string(name_identifier->content, providerId); + } else { + goto exit; + } + subject->NameIdentifier = name_identifier; + + /* SubjectConfirmation */ + subject_confirmation = lasso_saml_subject_confirmation_new(); + lasso_list_add_string(subject_confirmation->ConfirmationMethod, + LASSO_SAML_CONFIRMATION_METHOD_HOLDER_OF_KEY); + + /* Add public key value in credential */ + key_info = lasso_discovery_build_key_info_node(discovery, provider->providerID); + if (key_info != NULL) { + subject_confirmation->KeyInfo = key_info; + } + subject->SubjectConfirmation = subject_confirmation; + + /* Add the subject in the authentication statement */ + LASSO_SAML_SUBJECT_STATEMENT_ABSTRACT(authentication_statement)->Subject = subject; + assertion->AuthenticationStatement = authentication_statement; + + /* FIXME: add resource access statement */ + + /* Add credential to disco:QueryResponse */ + response = LASSO_DISCO_QUERY_RESPONSE(profile->response); + credentials = lasso_disco_credentials_new(); + lasso_list_add_gobject(credentials->any, assertion); + lasso_assign_gobject(response->Credentials, credentials); + + lasso_assign_string(assertionID, assertion->AssertionID); + +exit: + lasso_release_gobject(assertion); + lasso_release_gobject(credentials); + + return assertionID; +} static GHashTable * get_constructors_registry() @@ -1271,17 +1227,6 @@ get_xmlNode(LassoNode *node, gboolean lasso_dump) return xmlnode; } -static int -init_from_xml(LassoNode *node, xmlNode *xmlnode) -{ - int rc; - - rc = parent_class->init_from_xml(node, xmlnode); - if (rc) return rc; - - return 0; -} - /*****************************************************************************/ /* overrided parent class methods */ /*****************************************************************************/ @@ -1324,7 +1269,6 @@ class_init(LassoDiscoveryClass *klass) parent_class = g_type_class_peek_parent(klass); LASSO_NODE_CLASS(klass)->get_xmlNode = get_xmlNode; - LASSO_NODE_CLASS(klass)->init_from_xml = init_from_xml; G_OBJECT_CLASS(klass)->dispose = dispose; G_OBJECT_CLASS(klass)->finalize = finalize; diff --git a/lasso/id-wsf/discovery.h b/lasso/id-wsf/discovery.h index 4d676866..f8a77359 100644 --- a/lasso/id-wsf/discovery.h +++ b/lasso/id-wsf/discovery.h @@ -30,16 +30,16 @@ extern "C" { #endif /* __cplusplus */ -#include <lasso/xml/disco_insert_entry.h> -#include <lasso/xml/disco_modify.h> -#include <lasso/xml/disco_modify_response.h> -#include <lasso/xml/disco_query.h> -#include <lasso/xml/disco_query_response.h> -#include <lasso/xml/disco_remove_entry.h> -#include <lasso/xml/disco_requested_service_type.h> +#include "../xml/disco_insert_entry.h" +#include "../xml/disco_modify.h" +#include "../xml/disco_modify_response.h" +#include "../xml/disco_query.h" +#include "../xml/disco_query_response.h" +#include "../xml/disco_remove_entry.h" +#include "../xml/disco_requested_service_type.h" -#include <lasso/id-wsf/wsf_profile.h> -#include <lasso/id-wsf/data_service.h> +#include "wsf_profile.h" +#include "data_service.h" #define LASSO_TYPE_DISCOVERY (lasso_discovery_get_type()) #define LASSO_DISCOVERY(obj) \ @@ -60,8 +60,8 @@ struct _LassoDiscovery { LassoWsfProfile parent; /*< public >*/ - LassoDiscoResourceID *resource_id; - LassoDiscoEncryptedResourceID *encrypted_resource_id; + LassoDiscoResourceID *ResourceID; + LassoDiscoEncryptedResourceID *EncryptedResourceID; /*< private >*/ LassoDiscoveryPrivate *private_data; @@ -75,39 +75,31 @@ LASSO_EXPORT GType lasso_discovery_get_type(void); LASSO_EXPORT LassoDiscovery* lasso_discovery_new(LassoServer *server); -LASSO_EXPORT LassoDiscoInsertEntry* lasso_discovery_add_insert_entry(LassoDiscovery *discovery, +LASSO_EXPORT void lasso_discovery_destroy(LassoDiscovery *discovery); + +LASSO_EXPORT gint lasso_discovery_init_modify(LassoDiscovery *discovery, + const char *security_mech_id); + +LASSO_EXPORT gint lasso_discovery_add_insert_entry(LassoDiscovery *discovery, LassoDiscoServiceInstance *serviceInstance, LassoDiscoResourceID *resourceId); LASSO_EXPORT gint lasso_discovery_add_remove_entry(LassoDiscovery *discovery, const gchar *entryID); -LASSO_EXPORT LassoDiscoRequestedServiceType* lasso_discovery_add_requested_service_type( - LassoDiscovery *discovery, const gchar *service_type, const gchar *option); - -LASSO_EXPORT gint lasso_discovery_init_insert(LassoDiscovery *discovery, - LassoDiscoResourceOffering *new_offering, const char *security_mech_id); - -LASSO_EXPORT gint lasso_discovery_init_remove(LassoDiscovery *discovery, const char *entry_id); - -LASSO_EXPORT gint lasso_discovery_build_response_msg(LassoDiscovery *discovery); - -LASSO_EXPORT gint lasso_discovery_build_modify_response_msg(LassoDiscovery *discovery); - -LASSO_EXPORT G_GNUC_DEPRECATED gint lasso_discovery_init_modify(LassoDiscovery *discovery, - LassoDiscoResourceOffering *resourceOffering, LassoDiscoDescription *description); - LASSO_EXPORT gint lasso_discovery_init_query(LassoDiscovery *discovery, const gchar *security_mech_id); -LASSO_EXPORT gint lasso_discovery_process_modify_msg(LassoDiscovery *discovery, +LASSO_EXPORT gint lasso_discovery_add_requested_service_type( + LassoDiscovery *discovery, const gchar *service_type, const gchar *option); + +LASSO_EXPORT gint lasso_discovery_process_request_msg(LassoDiscovery *discovery, const gchar *message, const gchar *security_mech_id); +LASSO_EXPORT gint lasso_discovery_build_response_msg(LassoDiscovery *discovery); + LASSO_EXPORT gint lasso_discovery_process_modify_response_msg(LassoDiscovery *discovery, const gchar *message); -LASSO_EXPORT gint lasso_discovery_process_query_msg(LassoDiscovery *discovery, - const gchar *message, const char *security_mech_id); - LASSO_EXPORT gint lasso_discovery_process_query_response_msg(LassoDiscovery *discovery, const gchar *message); @@ -116,9 +108,6 @@ LASSO_EXPORT LassoWsfProfile* lasso_discovery_get_service(LassoDiscovery *discov LASSO_EXPORT GList* lasso_discovery_get_services(LassoDiscovery *discovery); -LASSO_EXPORT LassoDiscoDescription* lasso_discovery_get_description_auto( - const LassoDiscoResourceOffering *offering, const gchar *security_mech); - typedef LassoWsfProfile *(*LassoWsfProfileConstructor)(LassoServer *server, LassoDiscoResourceOffering *offering); diff --git a/lasso/id-wsf/interaction_profile_service.c b/lasso/id-wsf/interaction_profile_service.c index 19d93e23..8136680b 100644 --- a/lasso/id-wsf/interaction_profile_service.c +++ b/lasso/id-wsf/interaction_profile_service.c @@ -22,8 +22,13 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../xml/private.h" -#include <lasso/id-wsf/interaction_profile_service.h> +#include "./interaction_profile_service.h" +#include "./wsf_profile.h" +#include "../xml/soap_detail.h" +#include "../xml/soap_fault.h" +#include "../xml/is_redirect_request.h" +//#include "../xml/private.h" +#include "../utils.h" struct _LassoInteractionProfileServicePrivate { @@ -74,6 +79,33 @@ lasso_interaction_profile_service_process_response_msg(LassoInteractionProfileSe return 0; } +/** + * lasso_interaction_profile_service_build_redirect_response_msg: + * @profile: a #LassoWsfProfile + * @redirect_url: an #xmlChar string containing an HTTP url for interaction with the user + * + * The redirect_url must contain a way for the interaction service to link this interaction with the + * current request, usually it is the xml:id of the original request. + * + * Return value: 0 if successful, an error code otherwise. + */ +gint +lasso_interaction_profile_service_build_redirect_response_msg(LassoWsfProfile *profile, char *redirect_url) +{ + LassoSoapDetail *detail = NULL; + LassoSoapFault *fault = NULL; + + lasso_bad_param(WSF_PROFILE, profile); + + detail = lasso_soap_detail_new(); + fault = lasso_soap_fault_new(); + lasso_assign_new_gobject(fault->Detail, detail); + lasso_assign_string(fault->faultcode, LASSO_SOAP_FAULT_CODE_SERVER); + lasso_list_add_new_gobject(detail->any, lasso_is_redirect_request_new(redirect_url)); + + return lasso_wsf_profile_init_soap_response(profile, &fault->parent); +} + /*****************************************************************************/ /* private methods */ diff --git a/lasso/id-wsf/personal_profile_service.c b/lasso/id-wsf/personal_profile_service.c index 17b18ee9..025272f7 100644 --- a/lasso/id-wsf/personal_profile_service.c +++ b/lasso/id-wsf/personal_profile_service.c @@ -23,10 +23,11 @@ */ #include "../xml/private.h" -#include <lasso/id-wsf/personal_profile_service.h> -#include <lasso/id-wsf/data_service_private.h> -#include <lasso/id-wsf/discovery.h> - +#include "./personal_profile_service.h" +#include "./data_service.h" +#include "./wsf_profile_private.h" +#include "./discovery.h" +#include "../utils.h" /*****************************************************************************/ /* public methods */ @@ -38,41 +39,51 @@ lasso_personal_profile_service_get_email(LassoPersonalProfileService *service) xmlNode *xmlnode, *child; xmlChar *msgAccount = NULL, *msgProvider = NULL; char *email; + GList *answers = NULL; + gint rc = 0; g_return_val_if_fail(LASSO_IS_PERSONAL_PROFILE_SERVICE(service) == TRUE, NULL); - xmlnode = lasso_data_service_get_answer(LASSO_DATA_SERVICE(service), - "/pp:PP/pp:MsgContact"); + rc = lasso_data_service_get_answers_by_select(LASSO_DATA_SERVICE(service), + "/pp:PP/pp:MsgContact", &answers); + + lasso_foreach(answers, answers) + { + xmlnode = (xmlNode*)answers->data; + child = xmlnode->children; + while (child != NULL) { + if (child->type != XML_ELEMENT_NODE) { + child = child->next; + continue; + } + + if (strcmp((char *)child->name, "MsgAccount") == 0) { + msgAccount = xmlNodeGetContent(child); + } else if (strcmp((char *)child->name, "MsgProvider") == 0) { + msgProvider = xmlNodeGetContent(child); + } + + if (msgAccount != NULL && msgProvider != NULL) { + break; + } - child = xmlnode->children; - while (child != NULL) { - if (child->type != XML_ELEMENT_NODE) { child = child->next; - continue; - } - - if (strcmp((char *)child->name, "MsgAccount") == 0) { - msgAccount = xmlNodeGetContent(child); - } else if (strcmp((char *)child->name, "MsgProvider") == 0) { - msgProvider = xmlNodeGetContent(child); } - if (msgAccount != NULL && msgProvider != NULL) { + if (msgAccount && msgProvider) { + email = g_strdup_printf("%s@%s", msgAccount, msgProvider); break; + } else { + email = NULL; } - - child = child->next; - } - - if (msgAccount && msgProvider) { - email = g_strdup_printf("%s@%s", msgAccount, msgProvider); - } else { - email = NULL; + lasso_release_xml_string(msgAccount); + lasso_release_xml_string(msgProvider); + lasso_release_xml_node(xmlnode); } - xmlFree(msgAccount); - xmlFree(msgProvider); - xmlFreeNode(xmlnode); + lasso_release_xml_string(msgAccount); + lasso_release_xml_string(msgProvider); + lasso_release_xml_node(xmlnode); return email; } @@ -131,7 +142,7 @@ lasso_personal_profile_service_new_full(LassoServer *server, LassoDiscoResourceO return NULL; } - lasso_data_service_set_offering(LASSO_DATA_SERVICE(service), offering); + lasso_wsf_profile_set_resource_offering(&service->parent.parent, offering); return service; } diff --git a/lasso/id-wsf/wsf_profile.c b/lasso/id-wsf/wsf_profile.c index 8d153aec..e927db31 100644 --- a/lasso/id-wsf/wsf_profile.c +++ b/lasso/id-wsf/wsf_profile.c @@ -34,37 +34,42 @@ #include "../utils.h" -#include <lasso/id-wsf/wsf_profile.h> -#include <lasso/id-wsf/wsf_profile_private.h> -#include <lasso/id-wsf/discovery.h> -#include <lasso/id-wsf/utils.h> -#include <lasso/xml/disco_modify.h> -#include <lasso/xml/soap_fault.h> -#include <lasso/xml/soap_binding_correlation.h> -#include <lasso/xml/soap_binding_provider.h> -#include <lasso/xml/soap_binding_processing_context.h> -#include <lasso/xml/wsse_security.h> -#include <lasso/xml/saml_assertion.h> -#include <lasso/xml/saml_authentication_statement.h> -#include <lasso/xml/saml_subject_statement_abstract.h> -#include <lasso/xml/saml_subject.h> -#include <lasso/xml/ds_key_info.h> -#include <lasso/xml/ds_key_value.h> -#include <lasso/xml/ds_rsa_key_value.h> -#include <lasso/xml/soap_fault.h> -#include <lasso/xml/soap_detail.h> -#include <lasso/xml/is_redirect_request.h> - - -#include <lasso/id-ff/server.h> -#include <lasso/id-ff/providerprivate.h> -#include <lasso/id-ff/sessionprivate.h> +#include "wsf_profile.h" +#include "wsf_profile_private.h" +#include "discovery.h" +#include "utils.h" +#include "../xml/disco_modify.h" +#include "../xml/soap_fault.h" +#include "../xml/soap_binding_correlation.h" +#include "../xml/soap_binding_provider.h" +#include "../xml/soap_binding_processing_context.h" +#include "../xml/wsse_security.h" +#include "../xml/saml_assertion.h" +#include "../xml/saml_authentication_statement.h" +#include "../xml/saml_subject_statement_abstract.h" +#include "../xml/saml_subject.h" +#include "../xml/ds_key_info.h" +#include "../xml/ds_key_value.h" +#include "../xml/ds_rsa_key_value.h" +#include "../xml/soap_fault.h" +#include "../xml/soap_detail.h" +#include "../xml/is_redirect_request.h" + + +#include "../id-ff/server.h" +#include "../id-ff/providerprivate.h" +#include "../id-ff/sessionprivate.h" +#include "../xml/misc_text_node.h" /*****************************************************************************/ /* private methods */ /*****************************************************************************/ static gint lasso_wsf_profile_add_saml_signature(LassoWsfProfile *wsf_profile, xmlDoc *doc); +static LassoSoapBindingCorrelation* lasso_wsf_profile_utils_get_header_correlation(LassoSoapEnvelope + *envelope); +static char* lasso_wsf_profile_utils_get_message_id(LassoSoapEnvelope *envelope); +static char* lasso_wsf_profile_utils_get_ref_message_id(LassoSoapEnvelope *envelope); static struct XmlSnippet schema_snippets[] = { { "Server", SNIPPET_NODE_IN_CHILD, G_STRUCT_OFFSET(LassoWsfProfile, server), NULL, NULL, NULL}, @@ -81,18 +86,110 @@ static struct XmlSnippet schema_snippets[] = { {NULL, 0, 0, NULL, NULL, NULL} }; -/* - * lasso_wsf_profile_get_fault: +static LassoSoapBindingCorrelation* +lasso_wsf_profile_utils_get_header_correlation(LassoSoapEnvelope *envelope) +{ + LassoSoapHeader *header; + GList *header_list; + + if (LASSO_IS_SOAP_HEADER(envelope->Header)) { + header = envelope->Header; + } else { + goto cleanup; + } + lasso_foreach(header_list, header->Other) + { + if (LASSO_IS_SOAP_BINDING_CORRELATION(header_list->data)) { + return (LassoSoapBindingCorrelation*)header_list->data; + } + } +cleanup: + return NULL; +} + +static char* +lasso_wsf_profile_utils_get_ref_message_id(LassoSoapEnvelope *envelope) +{ + LassoSoapBindingCorrelation *correlation_header; + + correlation_header = lasso_wsf_profile_utils_get_header_correlation(envelope); + if (! correlation_header) { + return NULL; + } + return correlation_header->refToMessageID; +} + +static char* +lasso_wsf_profile_utils_get_message_id(LassoSoapEnvelope *envelope) +{ + LassoSoapBindingCorrelation *correlation_header; + + correlation_header = lasso_wsf_profile_utils_get_header_correlation(envelope); + if (! correlation_header) { + return NULL; + } + return correlation_header->messageID; +} +/** + * lasso_wsf_profile_build_soap_fault_response_msg: * @profile: a #LassoWsfProfile + * @rc: an error code from Lasso * - * Get the current fault present in profile private datas + * Build a new SOAP fault, eventually fill it with the given rc code */ -LassoSoapFault* -lasso_wsf_profile_get_fault(const LassoWsfProfile *profile) +gint +lasso_wsf_profile_build_soap_fault_response_msg(LassoWsfProfile *profile, gint rc) { - return profile->private_data->fault; + g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + lasso_assign_new_gobject(profile->response, lasso_soap_fault_new()); + if (rc) { + LassoMiscTextNode *node; + + if (rc == LASSO_PROFILE_ERROR_INVALID_MSG) { + lasso_assign_string(LASSO_SOAP_FAULT(profile->response)->faultcode, + LASSO_SOAP_ENV_PREFIX ":" LASSO_SOAP_FAULT_CODE_CLIENT); + } else { + lasso_assign_string(LASSO_SOAP_FAULT(profile->response)->faultcode, + LASSO_SOAP_ENV_PREFIX ":" LASSO_SOAP_FAULT_CODE_SERVER); + } + lasso_assign_string(LASSO_SOAP_FAULT(profile->response)->faultstring, + LASSO_SOAP_FAULT_STRING_SERVER); + lasso_assign_new_gobject(LASSO_SOAP_FAULT(profile->response)->Detail, lasso_soap_detail_new()); + node = (LassoMiscTextNode*)lasso_misc_text_node_new(); + lasso_assign_string(node->content, lasso_strerror(rc)); + node->name = "LassoError"; + node->ns_href = LASSO_LASSO_HREF; + node->ns_prefix = LASSO_LASSO_PREFIX; + } + return rc; } +/** + * lasso_wsf_set_msg_url_from_description: + * @profile: the #LassoWsfProfile object + * + * Initialize the @msgUrl attribute of the #LassoWsfProfile to the URL of the targetted web service. + * + * Return value: 0 if successful + */ +gint +lasso_wsf_profile_set_msg_url_from_description(LassoWsfProfile *wsf_profile) +{ + const LassoDiscoDescription *description = NULL; + int rc = 0; + + g_return_val_if_fail(LASSO_IS_WSF_PROFILE(wsf_profile), + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + description = lasso_wsf_profile_get_description(wsf_profile); + if (description->Endpoint != NULL) { + lasso_assign_string(wsf_profile->msg_url, description->Endpoint); + } else { + rc = LASSO_WSF_PROFILE_ERROR_MISSING_ENDPOINT; + } + return rc; +} /* Documentation of g_list_find_custom say that list element is the first pointer, * and user_data the second */ @@ -119,7 +216,7 @@ static gint lasso_wsf_profile_comply_with_saml_authentication(LassoWsfProfile *profile) { LassoSoapEnvelope *soap = NULL; - LassoSoapHeader *header; = NULL + LassoSoapHeader *header = NULL; LassoWsseSecurity *wsse_security = NULL; LassoSession *session = NULL; const LassoDiscoDescription *description = NULL; @@ -132,7 +229,8 @@ lasso_wsf_profile_comply_with_saml_authentication(LassoWsfProfile *profile) description = lasso_wsf_profile_get_description(profile); /* Lookup in the session the credential ref from the description and * add them to the SOAP header wsse:Security. */ - /* FIXME: should we really add every credentials to the message ? */ + /* FIXME: should we really add every credentials to the message, or only the one identifying + * us? */ goto_cleanup_if_fail_with_rc(description != NULL, LASSO_WSF_PROFILE_ERROR_MISSING_DESCRIPTION); credentialRefs = description->CredentialRef; goto_cleanup_if_fail_with_rc(credentialRefs != NULL, LASSO_WSF_PROFILE_ERROR_MISSING_CREDENTIAL_REF); @@ -149,7 +247,7 @@ lasso_wsf_profile_comply_with_saml_authentication(LassoWsfProfile *profile) while (credentialRefs) { char *ref = (char*)credentialRefs->data; xmlNode *assertion = lasso_session_get_assertion_by_id(session, ref); - goto_cleanup_if_fail(assertion != NULL, LASSO_WSF_PROFILE_ERROR_MISSING_CREDENTIAL_REF); + goto_cleanup_if_fail_with_rc(assertion != NULL, LASSO_WSF_PROFILE_ERROR_MISSING_CREDENTIAL_REF); lasso_list_add_xml_node(wsse_security->any, assertion); credentialRefs = g_list_next(credentialRefs); } @@ -182,6 +280,10 @@ lasso_wsf_profile_comply_with_security_mechanism(LassoWsfProfile *profile) if (lasso_security_mech_id_is_saml_authentication(sec_mech_id)) { return lasso_wsf_profile_comply_with_saml_authentication(profile); } + if (lasso_security_mech_id_is_bearer_authentication(sec_mech_id)) { + /* Same as SAML auth, add the tokens to wss:Security header */ + return lasso_wsf_profile_comply_with_saml_authentication(profile); + } if (lasso_security_mech_id_is_null_authentication(sec_mech_id)) { return 0; } @@ -259,7 +361,7 @@ lasso_wsf_profile_add_credential(G_GNUC_UNUSED LassoWsfProfile *profile, G_GNUC_ } /* - * lasso_wsf_profile_get_description_autos: + * lasso_wsf_profile_get_description_auto: * @si: a #LassoDiscoServiceInstance * @security_mech_id: the URI of a liberty security mechanism * @@ -326,8 +428,8 @@ lasso_wsf_profile_set_description_from_offering( offering->ServiceInstance->Description->data); } } else { - description = lasso_discovery_get_description_auto( - offering, security_mech_id); + description = lasso_wsf_profile_get_description_auto(offering->ServiceInstance, + security_mech_id); } if (description == NULL) { return LASSO_PROFILE_ERROR_MISSING_SERVICE_DESCRIPTION; @@ -339,10 +441,10 @@ lasso_wsf_profile_set_description_from_offering( /** * lasso_wsf_profile_set_security_mech_id: * @profile: the #LassoWsfProfile object - * @securit_mech_id: a char* string representing the chosen security mech id. + * @security_mech_id: a char* string representing the chosen security mech id. * * Set the security mechanism to use. Currently only SAML and NULL mechanism - * are supported for authentication. Transposrt is not handled by lasso so all + * are supported for authentication. Transport is not handled by lasso so all * are supported. * * List of supported mechanism ids: @@ -587,7 +689,7 @@ lasso_wsf_profile_is_identity_dirty(const LassoWsfProfile *profile) gboolean lasso_wsf_profile_is_session_dirty(const LassoWsfProfile *profile) { - return (profile->session && profile->session->is_dirty); + return (profile->session && lasso_session_is_dirty(profile->session)); } @@ -630,7 +732,6 @@ lasso_wsf_profile_set_session_from_dump(LassoWsfProfile *profile, const gchar * profile->session = lasso_session_new_from_dump(dump); if (profile->session == NULL) return critical_error(LASSO_PROFILE_ERROR_BAD_SESSION_DUMP); - profile->session->is_dirty = FALSE; return 0; } @@ -662,7 +763,34 @@ lasso_wsf_profile_init_soap_request(LassoWsfProfile *profile, LassoNode *request lasso_assign_new_gobject(profile->soap_envelope_request, envelope); lasso_list_add_gobject(envelope->Body->any, request); lasso_assign_gobject(profile->request, request); - return lasso_wsf_profile_comply_with_security_mechanism(profile); + return 0; +} + +/** + * lasso_wsf_profile_init_soap_response: + * @profile: a #LassoWsfProfile object + * @response: a #LassoNode object + * + * Build a new SOAP envelope containing response to current SOAP request + */ +gint +lasso_wsf_profile_init_soap_response(LassoWsfProfile *profile, LassoNode *response) +{ + char *providerID = NULL; + LassoSoapEnvelope *envelope = NULL; + + lasso_return_val_if_invalid_param(WSF_PROFILE, profile, + LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + + if (profile->server) { + providerID = profile->server->parent.ProviderID; + } + envelope = lasso_wsf_profile_build_soap_envelope_internal(lasso_wsf_profile_utils_get_message_id(profile->soap_envelope_request), + providerID); + lasso_assign_new_gobject(profile->soap_envelope_response, envelope); + lasso_list_add_gobject(envelope->Body->any, response); + lasso_assign_gobject(profile->response, response); + return 0; } /** @@ -676,7 +804,7 @@ lasso_wsf_profile_init_soap_request(LassoWsfProfile *profile, LassoNode *request * Return value: 0 if construction is successfull. **/ gint -lasso_wsf_profile_build_soap_request_msg(LassoWsfProfile *profile) +lasso_wsf_profile_build_soap_request_msg(LassoWsfProfile *wsf_profile) { LassoSoapEnvelope *envelope; xmlOutputBuffer *buf; @@ -686,33 +814,39 @@ lasso_wsf_profile_build_soap_request_msg(LassoWsfProfile *profile) char *sec_mech_id = NULL; int rc = 0; - g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(LASSO_IS_SOAP_ENVELOPE(profile->soap_envelope_request), - LASSO_SOAP_ERROR_MISSING_ENVELOPE); + lasso_bad_param(WSF_PROFILE, wsf_profile); + lasso_return_val_if_invalid_param(SOAP_ENVELOPE, wsf_profile->soap_envelope_request, + LASSO_SOAP_ERROR_MISSING_ENVELOPE); - envelope = profile->soap_envelope_request; + rc = lasso_wsf_profile_comply_with_security_mechanism(wsf_profile); + goto_cleanup_if_fail(rc == 0); + envelope = wsf_profile->soap_envelope_request; doc = xmlNewDoc((xmlChar*)"1.0"); envelope_node = lasso_node_get_xmlNode(LASSO_NODE(envelope), FALSE); xmlDocSetRootElement(doc, envelope_node); /* Sign request if necessary */ - sec_mech_id = profile->private_data->security_mech_id; + sec_mech_id = wsf_profile->private_data->security_mech_id; if (lasso_security_mech_id_is_saml_authentication(sec_mech_id)) { - rc = lasso_wsf_profile_add_saml_signature(profile, doc); + rc = lasso_wsf_profile_add_saml_signature(wsf_profile, doc); if (rc != 0) { goto cleanup; } + } else if (lasso_security_mech_id_is_bearer_authentication(sec_mech_id)) { + // Nothing to do } else if (lasso_security_mech_id_is_null_authentication(sec_mech_id) == FALSE) { rc = LASSO_WSF_PROFILE_ERROR_UNSUPPORTED_SECURITY_MECHANISM; goto cleanup; } + /* Dump soap request */ handler = xmlFindCharEncodingHandler("utf-8"); buf = xmlAllocOutputBuffer(handler); xmlNodeDumpOutput(buf, NULL, envelope_node, 0, 0, "utf-8"); xmlOutputBufferFlush(buf); - profile->msg_body = g_strdup( + wsf_profile->msg_body = g_strdup( (char*)(buf->conv ? buf->conv->content : buf->buffer->content)); lasso_release_output_buffer(buf); + rc = lasso_wsf_profile_set_msg_url_from_description(wsf_profile); cleanup: lasso_release_doc(doc); @@ -721,65 +855,78 @@ cleanup: /** * lasso_wsf_profile_build_soap_response_msg: - * @profile: the #LassoWsfProfile object + * @wsf_profile: a #LassoWsfProfile object * * Create the char* string containing XML document for the SOAP ID-WSF * response. * * Return value: 0 if construction is successfull. **/ -int -lasso_wsf_profile_build_soap_response_msg(LassoWsfProfile *profile) +gint +lasso_wsf_profile_build_soap_response_msg(LassoWsfProfile *wsf_profile) { - LassoSoapEnvelope *envelope; - xmlNode *soap_envelope; - xmlDoc *doc; - xmlOutputBuffer *buf; - xmlCharEncodingHandler *handler; + LassoSoapEnvelope *envelope = NULL; + LassoSoapFault *soap_fault = NULL; + int rc = 0; - lasso_return_val_if_invalid_param(WSF_PROFILE, profile, - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + lasso_bad_param(WSF_PROFILE, wsf_profile); + envelope = wsf_profile->soap_envelope_response; + if (! LASSO_IS_SOAP_ENVELOPE(envelope)) { + return LASSO_SOAP_ERROR_MISSING_ENVELOPE; + } - envelope = profile->soap_envelope_response; - doc = xmlNewDoc((xmlChar*)"1.0"); - soap_envelope = lasso_node_get_xmlNode(LASSO_NODE(envelope), TRUE); - xmlDocSetRootElement(doc, soap_envelope); - /* FIXME: does we need signature ? */ - /* Dump soap response */ - handler = xmlFindCharEncodingHandler("utf-8"); - buf = xmlAllocOutputBuffer(handler); - xmlNodeDumpOutput(buf, NULL, soap_envelope, 0, 0, "utf-8"); - xmlOutputBufferFlush(buf); - profile->msg_body = g_strdup( - (char*)(buf->conv ? buf->conv->content : buf->buffer->content)); - xmlOutputBufferClose(buf); - lasso_release_doc(doc); + /* If SOAP fault replace response by the SOAP fault */ + if ((soap_fault = lasso_wsf_profile_get_soap_fault(wsf_profile))) { + LassoSoapBody *body = NULL; + lasso_extract_node_or_fail(body, envelope->Body, SOAP_BODY, LASSO_SOAP_ERROR_MISSING_BODY); + lasso_release_list_of_gobjects(body->any); + lasso_list_add_gobject(body->any, soap_fault); + } - return 0; + lasso_assign_new_string(wsf_profile->msg_body, + lasso_node_export_to_xml((LassoNode*)envelope)); +cleanup: + return rc; } +/** FIXME: add support for security mechanisms SAML and Bearer. */ +/** + * lasso_wsf_profile_process_soap_request_msg: + * @profile: a #LassoWsfProfile object + * @message: a SOAP request message string + * @security_mech_id: the security mechanism to apply + * + * Process an ID-WSF SOAP request, extract headers information, and check compliance with the + * security mechanism. + * + * Return value: 0 if successful, an error code otherwise. + */ gint lasso_wsf_profile_process_soap_request_msg(LassoWsfProfile *profile, const gchar *message, - G_GNUC_UNUSED const gchar *service_type, const gchar *security_mech_id) + const gchar *security_mech_id) { LassoSoapBindingCorrelation *correlation = NULL; LassoSoapEnvelope *envelope = NULL; - gchar *messageId; + gchar *messageId = NULL; int rc = 0; - xmlDoc *doc; + xmlDoc *doc = NULL; GList *iter = NULL; + GList *node_list = NULL; - g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile), LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(message != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + lasso_bad_param(WSF_PROFILE, profile); + lasso_null_param(message); + + g_return_val_if_fail(profile->private_data, LASSO_PARAM_ERROR_NON_INITIALIZED_OBJECT); + lasso_wsf_profile_set_soap_fault(profile, NULL); doc = lasso_xml_parse_memory(message, strlen(message)); goto_cleanup_if_fail_with_rc (doc != NULL, critical_error(LASSO_PROFILE_ERROR_INVALID_SOAP_MSG)); /* Get soap request and his message id */ envelope = LASSO_SOAP_ENVELOPE(lasso_node_new_from_xmlNode(xmlDocGetRootElement(doc))); if (LASSO_IS_SOAP_ENVELOPE(envelope)) { - lasso_assign_gobject(profile->soap_envelope_request, LASSO_SOAP_ENVELOPE(envelope)); + lasso_assign_gobject(profile->soap_envelope_request, envelope); } else { - goto_cleanup_if_fail_with_rc(FALSE, LASSO_PROFILE_ERROR_INVALID_SOAP_MSG); + goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_SOAP_MSG); } goto_cleanup_if_fail_with_rc(envelope != NULL, LASSO_SOAP_ERROR_MISSING_ENVELOPE); goto_cleanup_if_fail_with_rc(envelope->Body != NULL, LASSO_SOAP_ERROR_MISSING_BODY); @@ -803,27 +950,31 @@ lasso_wsf_profile_process_soap_request_msg(LassoWsfProfile *profile, const gchar messageId = correlation->messageID; /* Comply with security mechanism */ if (lasso_security_mech_id_is_null_authentication(security_mech_id) == FALSE) { - /** FIXME: add security mechanisms */ goto_cleanup_if_fail_with_rc(FALSE, LASSO_WSF_PROFILE_ERROR_UNSUPPORTED_SECURITY_MECHANISM); } - /* Set soap response */ - lasso_release_gobject(envelope); - envelope = lasso_wsf_profile_build_soap_envelope_internal(messageId, - LASSO_PROVIDER(profile->server)->ProviderID); - lasso_assign_gobject(LASSO_WSF_PROFILE(profile)->soap_envelope_response, envelope); + /* Extract the remote provider ID if present */ + if (LASSO_IS_SOAP_HEADER(envelope->Header)) { + for (node_list = envelope->Header->Other; + node_list; node_list = g_list_next(node_list)) { + LassoSoapBindingProvider *node = node_list->data; -cleanup: - if (envelope) { - lasso_release_gobject(envelope); - } - if (doc) { - lasso_release_doc(doc); + if (LASSO_IS_SOAP_BINDING_PROVIDER(node)) { + lasso_assign_string(profile->private_data->remote_provider_id, + node->providerID); + break; /* Only treat the first one */ + } + } } +cleanup: + lasso_release_gobject(envelope); + lasso_release_doc(doc); + return rc; } + /** * lasso_wsf_profile_process_soap_response_msg: * @profile: a #LassoWsfProfile object @@ -838,34 +989,45 @@ gint lasso_wsf_profile_process_soap_response_msg(LassoWsfProfile *profile, const gchar *message) { xmlDoc *doc = NULL; - xmlNode *root = NULL; LassoSoapEnvelope *envelope = NULL; gint rc = 0; - g_return_val_if_fail(LASSO_IS_WSF_PROFILE(profile), - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(message != NULL, - LASSO_PARAM_ERROR_INVALID_VALUE); + lasso_bad_param(WSF_PROFILE, profile); + lasso_null_param(message); + + g_return_val_if_fail(profile->private_data, LASSO_PARAM_ERROR_NON_INITIALIZED_OBJECT); + lasso_wsf_profile_set_soap_fault(profile, NULL); doc = lasso_xml_parse_memory(message, strlen(message)); goto_cleanup_if_fail_with_rc (doc != NULL, critical_error(LASSO_PROFILE_ERROR_INVALID_SOAP_MSG)); - root = xmlDocGetRootElement(doc); - /* Parse the message */ - envelope = LASSO_SOAP_ENVELOPE(lasso_node_new_from_xmlNode(root)); + envelope = (LassoSoapEnvelope*)lasso_node_new_from_xmlNode(xmlDocGetRootElement(doc)); if (LASSO_IS_SOAP_ENVELOPE(envelope)) { - lasso_assign_gobject(profile->soap_envelope_response, LASSO_SOAP_ENVELOPE(envelope)); + lasso_assign_gobject(profile->soap_envelope_response, envelope); } else { - goto_cleanup_if_fail_with_rc(FALSE, LASSO_PROFILE_ERROR_INVALID_SOAP_MSG); + goto_cleanup_with_rc(LASSO_PROFILE_ERROR_INVALID_SOAP_MSG); } - goto_cleanup_if_fail_with_rc(envelope != NULL, LASSO_SOAP_ERROR_MISSING_ENVELOPE); goto_cleanup_if_fail_with_rc(envelope->Body != NULL, LASSO_SOAP_ERROR_MISSING_BODY); - if (envelope->Body->any) { - lasso_assign_gobject(profile->response, LASSO_NODE(envelope->Body->any->data)); + if (envelope->Body->any && LASSO_IS_NODE(envelope->Body->any->data)) { + lasso_assign_gobject(profile->response, envelope->Body->any->data); } else { - profile->response = NULL; - rc = LASSO_PROFILE_ERROR_MISSING_RESPONSE; + lasso_release_gobject(profile->response); + goto_cleanup_with_rc(LASSO_PROFILE_ERROR_MISSING_RESPONSE); } - /* XXX: Validate MessageID */ + + /* Check correlation header */ + goto_cleanup_if_fail_with_rc( + lasso_wsf_profile_utils_get_header_correlation( + profile->soap_envelope_response), + LASSO_WSF_PROFILE_ERROR_MISSING_CORRELATION); + + /* Check message ID */ + goto_cleanup_if_fail_with_rc( + g_strcmp0(lasso_wsf_profile_utils_get_message_id( + profile->soap_envelope_request), + lasso_wsf_profile_utils_get_ref_message_id( + profile->soap_envelope_response)) == 0, + LASSO_WSF_PROFILE_ERROR_INVALID_OR_MISSING_REFERENCE_TO_MESSAGE_ID); + /* Signal soap fault specifically, * find soap redirects. */ if (LASSO_IS_SOAP_FAULT(profile->response)) { @@ -887,12 +1049,8 @@ lasso_wsf_profile_process_soap_response_msg(LassoWsfProfile *profile, const gcha } } cleanup: - if (envelope) { - lasso_release_gobject(envelope); - } - if (doc) { - lasso_release_doc(doc); - } + lasso_release_gobject(envelope); + lasso_release_doc(doc); return rc; } @@ -923,6 +1081,12 @@ dispose(GObject *object) if (profile->private_data->dispose_has_run == TRUE) return; + lasso_release_string(profile->private_data->security_mech_id); + lasso_release_gobject(profile->private_data->offering); + lasso_release_gobject(profile->private_data->description); + lasso_release_string(profile->private_data->remote_provider_id); + lasso_release_gobject(profile->private_data->soap_fault); + lasso_release_string(profile->private_data->status_code); profile->private_data->dispose_has_run = TRUE; G_OBJECT_CLASS(parent_class)->dispose(object); @@ -1191,6 +1355,7 @@ add_key_info_security_token_reference(xmlDocPtr doc, xmlNode *signature, xmlChar xmlSetProp(reference, (xmlChar*) "URI", value); lasso_release(value); } + /** * lasso_wsf_profile_add_saml_signature: * @wsf_profile: a #LassoWsfProfile @@ -1306,3 +1471,129 @@ cleanup: lasso_release_xml_string(assertion_id); return rc; } + +/** + * lasso_wsf_profile_get_remote_provider_id: + * @wsf_profile: a #LassoWsfProfile object + * + * Return the remote provider id parsed in the last processing of a SOAP request or a SOAP response. + * + * Return value: the provider id string or NULL. + */ +const char* +lasso_wsf_profile_get_remote_provider_id(LassoWsfProfile *wsf_profile) +{ + lasso_return_val_if_invalid_param(WSF_PROFILE, wsf_profile, NULL); + + return wsf_profile->private_data->remote_provider_id; +} + +/** + * lasso_wsf_profile_get_remote_provider: + * @wsf_profile: a #LassoWsfProfile object + * @provider_ref: an output pointer to #LassoProvider object variable. + * + * Return the remote provider parsed in the last processing of a SOAP request or a SOAP response. + * + * Return value: 0 if successfull, LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID if no provider id + * is present in the SOAP headers, or LASSO_PROFILE_ERROR_UNKNOWN_PROVIDER if the provider is + * unknown to us. + */ +gint +lasso_wsf_profile_get_remote_provider(LassoWsfProfile *wsf_profile, LassoProvider **provider) +{ + LassoProvider *_provider = NULL; + + lasso_bad_param(WSF_PROFILE, wsf_profile); + + if (! wsf_profile->private_data->remote_provider_id) + return LASSO_PROFILE_ERROR_MISSING_REMOTE_PROVIDERID; + + if (! LASSO_IS_SERVER(wsf_profile->server)) + return LASSO_PROFILE_ERROR_UNKNOWN_PROVIDER; + + _provider = lasso_server_get_provider(wsf_profile->server, wsf_profile->private_data->remote_provider_id); + if (! _provider) + return LASSO_PROFILE_ERROR_UNKNOWN_PROVIDER; + + if (provider) { + lasso_assign_gobject(*provider, _provider); + } + return 0; +} + +/** + * lasso_wsf_profile_get_fault: + * @wsf_profile: a #LassoWsfProfile object + * + * If a fault is going to be returned as next response, return it. + * + * Return value: a #LassoSoapFault, or NULL if none is currently present in the object. + */ +LassoSoapFault* +lasso_wsf_profile_get_soap_fault(LassoWsfProfile *wsf_profile) +{ + lasso_return_val_if_invalid_param(WSF_PROFILE, wsf_profile, NULL); + + if (wsf_profile->private_data) + return wsf_profile->private_data->soap_fault; + return NULL; +} + +/** + * lasso_wsf_profile_set_soap_fault: + * @wsf_profile: a #LassoWsfProfile object + * @soap_fault: a #LassoSoapFault object + * + * Set a SOAP fault to be returned in next SOAP response message. The SOAP fault is removed by + * lasso_wsf_profile_init_soap_request. + * + * Return value: 0 if successful, an error code otherwise. + */ +gint +lasso_wsf_profile_set_soap_fault(LassoWsfProfile *wsf_profile, LassoSoapFault *soap_fault) +{ + lasso_bad_param(WSF_PROFILE, wsf_profile); + if (! LASSO_IS_SOAP_FAULT(soap_fault) && soap_fault) + return LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ; + if (! wsf_profile->private_data) + return LASSO_PARAM_ERROR_NON_INITIALIZED_OBJECT; + lasso_assign_gobject(wsf_profile->private_data->soap_fault, soap_fault); + return 0; +} + +/** + * lasso_wsf_profile_set_status_code: + * @wsf_profile: a #LassoWsfProfile + * @status_code: a string representing the status code + * + * Set the status code to set in the next built response. + * + * Return value: 0 if successful, an error code otherwise. + */ +gint +lasso_wsf_profile_set_status_code(LassoWsfProfile *wsf_profile, const char *status_code) +{ + lasso_bad_param(WSF_PROFILE, wsf_profile); + if (! wsf_profile->private_data) + return LASSO_PARAM_ERROR_NON_INITIALIZED_OBJECT; + lasso_assign_string(wsf_profile->private_data->status_code, status_code); + return 0; +} + +/** + * lasso_wsf_profile_get_status_code: + * @wsf_profile: a #LassoWsfProfile object + * + * Return the actual status code for this protocol object. + * + * Return value: a string owned by the profile object or NULL. + */ +const char* +lasso_wsf_profile_get_status_code(LassoWsfProfile *wsf_profile) { + lasso_return_val_if_invalid_param(WSF_PROFILE, wsf_profile, NULL); + + if (wsf_profile->private_data) + return wsf_profile->private_data->status_code; + return NULL; +} diff --git a/lasso/id-wsf/wsf_profile.h b/lasso/id-wsf/wsf_profile.h index ffd0cba8..a71f05bf 100644 --- a/lasso/id-wsf/wsf_profile.h +++ b/lasso/id-wsf/wsf_profile.h @@ -30,15 +30,16 @@ extern "C" { #endif /* __cplusplus */ -#include <lasso/id-ff/server.h> -#include <lasso/id-ff/identity.h> -#include <lasso/id-ff/session.h> -#include <lasso/xml/soap_envelope.h> -#include <lasso/xml/soap_binding_provider.h> -#include <lasso/xml/saml_assertion.h> -#include <lasso/xml/disco_description.h> -#include <lasso/xml/disco_resource_offering.h> -#include <lasso/xml/disco_description.h> +#include <../id-ff/server.h> +#include <../id-ff/identity.h> +#include <../id-ff/session.h> +#include <../xml/soap_envelope.h> +#include <../xml/soap_binding_provider.h> +#include <../xml/soap_fault.h> +#include <../xml/saml_assertion.h> +#include <../xml/disco_description.h> +#include <../xml/disco_resource_offering.h> +#include <../xml/disco_description.h> #define LASSO_TYPE_WSF_PROFILE (lasso_wsf_profile_get_type()) #define LASSO_WSF_PROFILE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ @@ -102,11 +103,13 @@ LASSO_EXPORT gint lasso_wsf_profile_build_soap_request_msg(LassoWsfProfile *prof LASSO_EXPORT gint lasso_wsf_profile_build_soap_response_msg(LassoWsfProfile *profile); -LASSO_EXPORT gint lasso_wsf_profile_init_soap_request(LassoWsfProfile *profile, - LassoNode *request); +LASSO_EXPORT gint lasso_wsf_profile_init_soap_request(LassoWsfProfile *profile, LassoNode *request); + +LASSO_EXPORT gint lasso_wsf_profile_init_soap_response(LassoWsfProfile *profile, LassoNode + *response); LASSO_EXPORT gint lasso_wsf_profile_process_soap_request_msg(LassoWsfProfile *profile, - const gchar *message, const gchar *service_type, const gchar *security_mech_id); + const gchar *message, const gchar *security_mech_id); LASSO_EXPORT gint lasso_wsf_profile_process_soap_response_msg(LassoWsfProfile *profile, const gchar *message); @@ -156,6 +159,31 @@ G_GNUC_DEPRECATED LASSO_EXPORT void lasso_wsf_profile_set_principal_offline( LASSO_EXPORT gint lasso_wsf_profile_init(LassoWsfProfile *profile, LassoServer *server, LassoDiscoResourceOffering *offering); +LASSO_EXPORT gint lasso_wsf_profile_get_remote_provider(LassoWsfProfile *wsf_profile, + LassoProvider **provider); + +LASSO_EXPORT const char* lasso_wsf_profile_get_remote_provider_id(LassoWsfProfile *wsf_profile); + +LASSO_EXPORT LassoSoapFault* lasso_wsf_profile_get_soap_fault(LassoWsfProfile *wsf_profile); + +LASSO_EXPORT gint lasso_wsf_profile_set_soap_fault(LassoWsfProfile *wsf_profile, LassoSoapFault *soap_fault); + +LASSO_EXPORT gint lasso_wsf_profile_set_status_code(LassoWsfProfile *wsf_profile, const char *code); + +LASSO_EXPORT const char* lasso_wsf_profile_get_status_code(LassoWsfProfile *wsf_profile); + +#define lasso_wsf_profile_helper_assign_resource_id(from,to) \ + if ((from)->ResourceID) {\ + lasso_assign_gobject((to)->ResourceID, (from)->ResourceID); \ + } else if ((from)->EncryptedResourceID) {\ + lasso_assign_gobject((to)->EncryptedResourceID, (from)->EncryptedResourceID); \ + } + +#define lasso_wsf_profile_helper_set_status(message, code) \ + { \ + lasso_assign_new_gobject(message->Status, lasso_utility_status_new(code)); \ + } + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/lasso/id-wsf/wsf_profile_private.h b/lasso/id-wsf/wsf_profile_private.h index a8f25925..859cee1d 100644 --- a/lasso/id-wsf/wsf_profile_private.h +++ b/lasso/id-wsf/wsf_profile_private.h @@ -30,7 +30,7 @@ extern "C" { #endif /* __cplusplus */ -#include <lasso/xml/soap_fault.h> +#include "../xml/soap_fault.h" struct _LassoWsfProfilePrivate { @@ -38,16 +38,18 @@ struct _LassoWsfProfilePrivate char *security_mech_id; LassoDiscoResourceOffering *offering; LassoDiscoDescription *description; - LassoSoapFault *fault; + char *remote_provider_id; + LassoSoapFault *soap_fault; + char *status_code; }; LassoSoapFault* lasso_wsf_profile_get_fault(const LassoWsfProfile *profile); - LassoDiscoDescription* lasso_wsf_profile_get_description_auto(const LassoDiscoServiceInstance *si, const gchar *security_mech_id); - void lasso_wsf_profile_set_resource_offering(LassoWsfProfile *profile, LassoDiscoResourceOffering *offering); +gint lasso_wsf_profile_set_msg_url_from_description(LassoWsfProfile *wsf_profile); +gint lasso_wsf_profile_build_soap_fault_response_msg(LassoWsfProfile *profile, gint rc); #ifdef __cplusplus } |