diff options
Diffstat (limited to 'lasso/id-wsf-2.0/profile.c')
-rw-r--r-- | lasso/id-wsf-2.0/profile.c | 660 |
1 files changed, 547 insertions, 113 deletions
diff --git a/lasso/id-wsf-2.0/profile.c b/lasso/id-wsf-2.0/profile.c index 62347317..5086a833 100644 --- a/lasso/id-wsf-2.0/profile.c +++ b/lasso/id-wsf-2.0/profile.c @@ -35,6 +35,8 @@ #include "../id-ff/serverprivate.h" #include "../id-ff/providerprivate.h" +#include "../saml-2.0/profileprivate.h" + #include "profile.h" #include "session.h" @@ -43,22 +45,85 @@ #include "../xml/soap_binding_provider.h" #include "../xml/soap_binding_processing_context.h" #include "../xml/xml_enc.h" +#include "../xml/id-wsf-2.0/sb2_sender.h" +#include "../xml/id-wsf-2.0/sb2_redirect_request.h" #include "../xml/ws/wsse_security_header.h" #include "../xml/saml-2.0/saml2_assertion.h" #include "../utils.h" +#include "./idwsf2_helper.h" +#include "./soap_binding.h" +#include "../id-wsf/utils.h" +#include "../saml-2.0/saml2_helper.h" -/*****************************************************************************/ -/* private methods */ -/*****************************************************************************/ +/** + * LassoIdWsf2ProfilePrivate: + * @epr: the #LassoWsAddrEndpointReference object representing the targetd service + */ +struct _LassoIdWsf2ProfilePrivate { + LassoWsAddrEndpointReference *epr; + LassoSoapEnvelope *soap_envelope_request; + LassoSoapEnvelope *soap_envelope_response; +}; + +#define private_accessors(type, name) \ +static type \ +_get_##name(LassoIdWsf2Profile *idwsf2_profile)\ +{ \ + if (idwsf2_profile && idwsf2_profile->private_data) \ + { \ + return idwsf2_profile->private_data->name; \ + } \ + return 0; \ +} \ +static void \ +_set_##name(LassoIdWsf2Profile *idwsf2_profile, \ + type what) \ +{ \ + if (idwsf2_profile && idwsf2_profile->private_data) \ + { \ + lasso_assign_gobject(idwsf2_profile->private_data->name, what); \ + } \ +} -LassoSoapEnvelope* -lasso_idwsf2_profile_build_soap_envelope(G_GNUC_UNUSED const char *refToMessageId, G_GNUC_UNUSED const char *providerId) +private_accessors(LassoWsAddrEndpointReference*,epr) +private_accessors(LassoSoapEnvelope*,soap_envelope_request) +private_accessors(LassoSoapEnvelope*,soap_envelope_response) + + +static void +_add_fault_for_rc(LassoIdWsf2Profile *profile, int rc) +{ + LassoSoapFault *fault; + char *code; + + if (rc) { + code = g_strdup_printf("LASSO_ERROR_%i", rc); + fault = lasso_soap_fault_new_full(code, lasso_strerror(rc)); + g_free(code); + lasso_release_list_of_gobjects(_get_soap_envelope_response(profile)->Header->Other); + lasso_soap_envelope_add_to_body(_get_soap_envelope_response(profile), (LassoNode*)fault); + } +} + +/** + * lasso_idwsf2_profile_build_soap_envelope: + * @refToMessageId: (allow-none): the string ID of the request + * @providerId: (allow-none): the providerID of the sender + * + * Build a new SOAP envelope, for transmitting an ID-WSF request of response. If the message is a + * response, refer to the request whose ID is @refToMessageId. + * + * Return value: a new #LassoSoapEnvelope if successful, NULL otherwise. + */ +static LassoSoapEnvelope* +lasso_idwsf2_profile_build_soap_envelope(const char *refToMessageId, const char *providerID) { LassoSoapEnvelope *envelope; LassoSoapHeader *header; LassoSoapBody *body; + LassoIdWsf2Sb2Sender *sender; /* Body */ body = lasso_soap_body_new(); @@ -69,125 +134,424 @@ lasso_idwsf2_profile_build_soap_envelope(G_GNUC_UNUSED const char *refToMessageI header = lasso_soap_header_new(); envelope->Header = header; + if (providerID) { + /* Sender */ + sender = lasso_idwsf2_sb2_sender_new(); + lasso_assign_string(sender->providerID, providerID); + lasso_list_add_gobject(header->Other, sender); + } + + if (refToMessageId) { + LassoWsAddrAttributedURI *relates_to; + relates_to = lasso_wsa_attributed_uri_new_with_string(refToMessageId); + lasso_node_set_custom_nodename((LassoNode*)relates_to, "RelatesTo"); + lasso_list_add_gobject(header->Other, relates_to); + } + return envelope; } -/*****************************************************************************/ -/* public methods */ -/*****************************************************************************/ - +/** + * lasso_idwsf2_profile_init_request: + * @profile: a #LassoIdWsf2Profile object + * + * Initialize a new SOAP ID-WSF 2.0 request. Clear the existing request if one is currently set. + * + * Return value: 0 if successful, an error code otherwise. + */ gint -lasso_idwsf2_profile_init_soap_request(LassoIdWsf2Profile *profile, LassoNode *request, - gchar *service_type) +lasso_idwsf2_profile_init_request(LassoIdWsf2Profile *idwsf2_profile) { - LassoSoapEnvelope *envelope; - LassoSession *session = LASSO_PROFILE(profile)->session; - LassoSaml2Assertion *assertion; - LassoWsSec1SecurityHeader *wsse_security; - - /* Initialise soap envelope */ - envelope = lasso_idwsf2_profile_build_soap_envelope(NULL, - LASSO_PROVIDER(LASSO_PROFILE(profile)->server)->ProviderID); - lasso_assign_new_gobject(profile->soap_envelope_request, envelope); - - /* Add identity token (if it exists in the session) in soap header */ - assertion = lasso_session_get_assertion_identity_token(session, service_type); - - /* FIXME: use sb2:TargetIdentity if security mech is :null */ - if (assertion != NULL) { - wsse_security = lasso_wsse_security_header_new(); - lasso_list_add_new_gobject(wsse_security->any, assertion); - lasso_list_add_new_gobject(envelope->Header->Other, wsse_security); + LassoSoapEnvelope *envelope = NULL; + LassoProfile *profile = NULL; + LassoWsAddrEndpointReference *epr; + const char *provider_id = NULL; + int rc = 0; + + lasso_bad_param(IDWSF2_PROFILE, idwsf2_profile); + profile = &idwsf2_profile->parent; + epr = lasso_idwsf2_profile_get_epr(idwsf2_profile); + + if (epr) { + LassoIdWsf2DiscoSecurityContext *security_context; + + security_context = + lasso_wsa_endpoint_reference_get_idwsf2_security_context_for_security_mechanism( + epr, lasso_security_mech_id_is_bearer_authentication, NULL, FALSE); + if (! security_context) { + return LASSO_WSF_PROFILE_ERROR_UNSUPPORTED_SECURITY_MECHANISM; + } } - /* Add the given request in soap body */ - lasso_list_add_gobject(envelope->Body->any, request); + if (LASSO_IS_SERVER(profile->server)) { + provider_id = profile->server->parent.ProviderID; + } + envelope = lasso_idwsf2_profile_build_soap_envelope(NULL, provider_id); + _set_soap_envelope_request(idwsf2_profile, envelope); + lasso_release_gobject(profile->request); - return 0; + lasso_release_gobject(envelope); + return rc; } +/** + * lasso_idwsf2_profile_init_response: + * @profile: a #LassoIdWsf2Profile object + * + * Initialize a new SOAP ID-WSF 2.0 response. Clear the existing response if one is currently set. + * + * Return value: 0 if successful, an error code otherwise. + */ gint -lasso_idwsf2_profile_build_request_msg(LassoIdWsf2Profile *profile) +lasso_idwsf2_profile_init_response(LassoIdWsf2Profile *profile) { - g_return_val_if_fail(LASSO_IS_IDWSF2_PROFILE(profile), - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); + char *provider_id = NULL; + LassoSoapEnvelope *soap_envelope; + char *request_message_id = NULL; + int rc = 0; + + lasso_bad_param(IDWSF2_PROFILE, profile); + + if (LASSO_IS_SERVER(profile->parent.server)) { + provider_id = profile->parent.server->parent.ProviderID; + } + request_message_id = lasso_soap_envelope_get_message_id( + lasso_idwsf2_profile_get_soap_envelope_request(profile)); + soap_envelope = lasso_idwsf2_profile_build_soap_envelope(request_message_id, provider_id); + _set_soap_envelope_response(profile, soap_envelope); + lasso_release_gobject(profile->parent.response); + + return rc; +} + +/** + * lasso_idwsf2_profile_build_request_msg: + * @profile: a #LassoIdWsf2Profile object + * + * Serialize and sign, if needed, the SOAP request message, put the result in + * <programlisting>LASSO_PROFILE(profile)->msg_body</paramlisting>. + * + * FIXME: really do sign messages. + * + * Return value: 0 if successful, LASSO_PROFILE_ERROR_BUILDING_REQUEST_FAILED. + */ +gint +lasso_idwsf2_profile_build_request_msg(LassoIdWsf2Profile *profile, const char *security_mech_id) +{ + LassoWsAddrEndpointReference *epr; + LassoSoapEnvelope *envelope; + + lasso_bad_param(IDWSF2_PROFILE, profile); + epr = lasso_idwsf2_profile_get_epr(profile); + envelope = _get_soap_envelope_request(profile); + + /* Handle SOAP Binding and WS-Security, when given an EPR */ + if (LASSO_IS_WSA_ENDPOINT_REFERENCE(epr)) { + if (epr->Address != NULL) { + lasso_assign_string(profile->parent.msg_url, epr->Address->content); + } + + /* Default try bearer */ + if (security_mech_id == NULL || lasso_security_mech_id_is_bearer_authentication( + security_mech_id)) { + LassoNode *security_token; + + security_token = lasso_wsa_endpoint_reference_get_security_token(epr, + lasso_security_mech_id_is_bearer_authentication, NULL); + if (security_token) { + lasso_soap_envelope_add_security_token (envelope, security_token); + } else { + g_warning ("No security mechanism specified, " \ + "failed to find security token for Bearer mechanism"); + } + if (lasso_wsa_endpoint_reference_get_target_identity_token(epr, + lasso_security_mech_id_is_bearer_authentication, NULL) != NULL) { + g_critical("TargetIdentity token are not supported"); + } + } else { + g_critical("Only Bearer security mechanism is supported by ID-WSF 2.0 module of Lasso"); + } + } LASSO_PROFILE(profile)->msg_body = lasso_node_export_to_xml( - LASSO_NODE(profile->soap_envelope_request)); + LASSO_NODE(_get_soap_envelope_request(profile))); + + if (! LASSO_PROFILE(profile)->msg_body) + return LASSO_PROFILE_ERROR_BUILDING_REQUEST_FAILED; return 0; } +/** + * lasso_idwsf2_profile_process_request_msg: + * @wsf2_profile: a #LassoIdWsf2Profile object + * @message: a received SOAP message + * + * Parse a SOAP request message and initialize the SOAP Envelope for the response. + * + * Return value: 0 if successful, an error code otherwise among: + * <itemizedlist> + * <listitem><para>LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ if @profile is not a #LassoIdWsf2Profile + * object,</para></listitem> + * <listitem><para>LASSO_PARAM_ERROR_INVALID_VALUE if message is NULL,</para></listitem> + * <listitem><para>LASSO_PROFILE_ERROR_INVALID_MSG if we cannot parse the message,</para></listitem> + * <listitem><para>LASSO_SOAP_ERROR_MISSING_BODY if the message has no body + * content.</para></listitem> + * <itemizedlist> + */ gint -lasso_idwsf2_profile_process_soap_request_msg(LassoIdWsf2Profile *wsf2_profile, const gchar *message) +lasso_idwsf2_profile_process_request_msg(LassoIdWsf2Profile *wsf2_profile, const gchar *message) { LassoProfile *profile = NULL; LassoSoapEnvelope *envelope = NULL; + char *message_id; + char *provider_id; int rc = 0; - g_return_val_if_fail(LASSO_IS_IDWSF2_PROFILE(wsf2_profile), - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - g_return_val_if_fail(message != NULL, LASSO_PARAM_ERROR_INVALID_VALUE); + lasso_bad_param(IDWSF2_PROFILE, wsf2_profile); + lasso_check_non_empty_string(message); + + /* Clean some fields */ + lasso_release_gobject(wsf2_profile->parent.nameIdentifier); + lasso_release_string(wsf2_profile->parent.remote_providerID); + lasso_release_string(wsf2_profile->parent.msg_body); + lasso_release_gobject(wsf2_profile->private_data->soap_envelope_response); + lasso_release_gobject(wsf2_profile->parent.response); /* Get soap request */ profile = LASSO_PROFILE(wsf2_profile); - lasso_assign_new_gobject(wsf2_profile->soap_envelope_request, lasso_soap_envelope_new_from_message(message)); - if (! LASSO_IS_SOAP_ENVELOPE(wsf2_profile->soap_envelope_request)) { + + lasso_assign_new_gobject(wsf2_profile->private_data->soap_envelope_request, + lasso_soap_envelope_new_from_message(message)); + if (! LASSO_IS_SOAP_ENVELOPE(_get_soap_envelope_request(wsf2_profile))) { return LASSO_PROFILE_ERROR_INVALID_MSG; } - envelope = wsf2_profile->soap_envelope_request; + envelope = _get_soap_envelope_request(wsf2_profile); if (envelope != NULL && envelope->Body != NULL && envelope->Body->any != NULL && LASSO_IS_NODE(envelope->Body->any->data)) { - lasso_assign_gobject(LASSO_PROFILE(profile)->request, (LassoNode*)envelope->Body->any->data); + lasso_assign_gobject(profile->request, envelope->Body->any->data); } else { rc = LASSO_SOAP_ERROR_MISSING_BODY; } /* Initialize soap response */ - lasso_assign_new_gobject(wsf2_profile->soap_envelope_response, lasso_idwsf2_profile_build_soap_envelope(NULL, - LASSO_PROVIDER(profile->server)->ProviderID)); + message_id = lasso_soap_envelope_get_message_id( + _get_soap_envelope_request(wsf2_profile)); + if (LASSO_IS_SERVER(profile->server)) { + provider_id = profile->server->parent.ProviderID; + lasso_assign_new_gobject(wsf2_profile->private_data->soap_envelope_response, + lasso_idwsf2_profile_build_soap_envelope(message_id, provider_id)); + } + _add_fault_for_rc(wsf2_profile, rc); +cleanup: return rc; } +/** + * lasso_idwsf2_profile_check_security_mechanism: + * @profile: a #LassoIdWsf2Profile object + * @security_mech_id:(allow-none): the security mechanism to enforce, if none is provided Bearer is + * assumed. + * + * Check ID-WSF 2.0 Security Mechanism upon the received request. + * + * Return value: 0 if the request passed the check, an error code otherwise. + */ gint -lasso_idwsf2_profile_build_response_msg(LassoIdWsf2Profile *profile) +lasso_idwsf2_profile_check_security_mechanism(LassoIdWsf2Profile *profile, + const char *security_mech_id) { - g_return_val_if_fail(LASSO_IS_IDWSF2_PROFILE(profile), - LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ); - - LASSO_PROFILE(profile)->msg_body = lasso_node_export_to_xml(LASSO_NODE( - profile->soap_envelope_response)); + LassoSoapEnvelope *envelope = NULL; + int rc = LASSO_WSF_PROFILE_ERROR_SECURITY_MECHANISM_CHECK_FAILED; + + lasso_bad_param(IDWSF2_PROFILE, profile); + envelope = _get_soap_envelope_request(profile); + /* Verify security mechanism */ + if (security_mech_id == NULL || + lasso_security_mech_id_is_bearer_authentication(security_mech_id)) { + LassoSaml2Assertion *assertion; + LassoProvider *issuer; + + assertion = lasso_soap_envelope_get_saml2_security_token (envelope); + if (assertion == NULL) + goto cleanup; + if (! lasso_saml2_assertion_validate_conditions(assertion, NULL)) + goto cleanup; + issuer = lasso_saml2_assertion_get_issuer_provider(assertion, profile->parent.server); + if (! issuer || issuer->role != LASSO_PROVIDER_ROLE_IDP) + goto cleanup; + if (lasso_provider_verify_single_node_signature(issuer, (LassoNode*)assertion, "ID") != 0) + goto cleanup; + } else { + g_warning("Only Bearer mechanism is supported!"); + rc = LASSO_ERROR_UNIMPLEMENTED; + goto cleanup; + } + rc = 0; +cleanup: + _add_fault_for_rc(profile, rc); + return rc; +} - return 0; +/** + * lasso_idwsf2_profile_init_soap_fault_response: + * @profile: a #LassoIdWsf2Profile object + * + * Initialize a new SOAP 1.1 fault. + * + * Return value: 0 if successful, an error code otherwise. + */ +gint +lasso_idwsf2_profile_init_soap_fault_response(LassoIdWsf2Profile *profile) +{ + int rc = 0; + LassoSoapEnvelope *envelope; + LassoSoapFault *fault; + + lasso_check_good_rc(lasso_idwsf2_profile_init_response(profile)); + envelope = lasso_idwsf2_profile_get_soap_envelope_response(profile); + if (envelope) { + fault = lasso_soap_fault_new(); + lasso_list_add_new_gobject(envelope->Body->any, fault); + lasso_assign_gobject(profile->parent.response, fault); + } +cleanup: + return rc; } +/** + * lasso_idwsf2_profile_redirect_user_for_interaction: + * @profile: a #LassoIdWsf2Profile object + * @redirect_url: an URL where the user must be redirected + * + * Create a SOAP fault asking for user + * + * Return value: 0 if successful, an error code otherwise. + */ gint -lasso_idwsf2_profile_process_soap_response_msg(LassoIdWsf2Profile *profile, const gchar *message) +lasso_idwsf2_profile_redirect_user_for_interaction( + LassoIdWsf2Profile *profile, const gchar *redirect_url, gboolean for_data) { - LassoSoapEnvelope *envelope = NULL; - int res = 0; + LassoSoapFault *fault = NULL; + LassoIdWsf2Sb2RedirectRequest *redirect_request = NULL; + LassoIdWsf2Sb2UserInteractionHint hint; + int rc = 0; - g_return_val_if_fail(LASSO_IS_IDWSF2_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(IDWSF2_PROFILE, profile); + lasso_check_non_empty_string(redirect_url); + + hint = lasso_soap_envelope_get_sb2_user_interaction_hint( + lasso_idwsf2_profile_get_soap_envelope_request(profile)); + switch (hint) { + case LASSO_IDWSF2_SB2_USER_INTERACTION_HINT_DO_NOT_INTERACT: + return LASSO_WSF_PROFILE_ERROR_SERVER_INTERACTION_REQUIRED; + case LASSO_IDWSF2_SB2_USER_INTERACTION_HINT_DO_NOT_INTERACT_FOR_DATA: + if (for_data) { + return LASSO_WSF_PROFILE_ERROR_SERVER_INTERACTION_REQUIRED_FOR_DATA; + } + default: + break; + } - /* Get soap response */ - envelope = lasso_soap_envelope_new_from_message(message); + lasso_check_good_rc(lasso_idwsf2_profile_init_soap_fault_response(profile)); + fault = (LassoSoapFault*)profile->parent.response; + lasso_assign_string(fault->faultcode, LASSO_SOAP_FAULT_CODE_SERVER); + lasso_assign_string(fault->faultstring, "Server error"); + redirect_request = lasso_idwsf2_sb2_redirect_request_new_full(redirect_url); + lasso_soap_fault_add_to_detail(fault, (LassoNode*)redirect_request); + +cleanup: + lasso_release_gobject(redirect_request); + return rc; +} +/** + * lasso_idwsf2_profile_build_response_msg: + * @idwsf2_profile: a #LassoIdWsf2Profile object + * + * Serialize and sign the SOAP, if needed, the response message, put the result in + * <programlisting>LASSO_PROFILE(profile)->msg_body</paramlisting>. + * + * Return value: 0 if successful, LASSO_PROFILE_ERROR_BUILDING_RESPONSE_FAILED otherwise. + */ +gint +lasso_idwsf2_profile_build_response_msg(LassoIdWsf2Profile *idwsf2_profile) +{ + LassoSoapEnvelope *envelope; - lasso_assign_new_gobject(profile->soap_envelope_response, envelope); + lasso_bad_param(IDWSF2_PROFILE, idwsf2_profile); - if (envelope != NULL && envelope->Body != NULL && envelope->Body->any != NULL) { - lasso_assign_gobject(LASSO_PROFILE(profile)->response, LASSO_NODE(envelope->Body->any->data)); - } else { - res = LASSO_SOAP_ERROR_MISSING_BODY; + envelope = lasso_idwsf2_profile_get_soap_envelope_response(idwsf2_profile); + if (envelope == NULL) { + return LASSO_PROFILE_ERROR_MISSING_RESPONSE; } + idwsf2_profile->parent.msg_body = lasso_node_export_to_xml((LassoNode*)envelope); - if (LASSO_PROFILE(profile)->response == NULL) { - res = LASSO_PROFILE_ERROR_MISSING_RESPONSE; + if (! LASSO_PROFILE(idwsf2_profile)->msg_body) { + return LASSO_PROFILE_ERROR_BUILDING_RESPONSE_FAILED; } + return 0; +} - return res; +/** + * lasso_idwsf2_profile_process_response_msg: + * @profile: a #LassoIdWsf2Profile object + * @message: a string containing a response message + * + * Parse a response received by SOAP. Place the parsed message in the #LassoIdWsf2Profile structure + * in the @soap_envelope_response field and the content of the body in the @response field. + * + * Return value: 0 if successful, one of those error codes if the call fails: <itemizedlist> + * <listitem><para>LASSO_PARAM_ERROR_BAD_TYPE_OR_NULL_OBJ if first parameter is not + * a #LassoIdWsf2Profile object,</para></listitem> + * <listitem><para>LASSO_PARAM_ERROR_INVALID_VALUE if message is NULL,</para></listitem> + * <listitem><para>LASSO_SOAP_ERROR_MISSING_BODY if no body element is found,</para></listitem> + * <listitem><para>LASSO_PROFILE_ERROR_MISSING_RESPONSE if the body element is + * empty.</para></listitem> + */ +gint +lasso_idwsf2_profile_process_response_msg(LassoIdWsf2Profile *profile, const gchar *message) +{ + LassoSoapEnvelope *envelope = NULL; + int rc = 0; + + lasso_bad_param(IDWSF2_PROFILE, profile); + lasso_check_non_empty_string(message); + + envelope = lasso_soap_envelope_new_from_message(message); + _set_soap_envelope_response(profile, envelope); + + goto_cleanup_if_fail_with_rc (envelope != NULL, + LASSO_PROFILE_ERROR_INVALID_RESPONSE); + goto_cleanup_if_fail_with_rc (envelope->Body != NULL, + LASSO_SOAP_ERROR_MISSING_BODY); + goto_cleanup_if_fail_with_rc (envelope->Body->any != NULL && + LASSO_IS_NODE(envelope->Body->any->data), + LASSO_PROFILE_ERROR_MISSING_RESPONSE); + + lasso_assign_gobject(profile->parent.response, + envelope->Body->any->data); + + if (LASSO_IS_SOAP_FAULT(profile->parent.response)) { + LassoSoapFault *fault = (LassoSoapFault*)profile->parent.response; + if (LASSO_IS_SOAP_DETAIL(fault->Detail)) { + LassoIdWsf2Sb2RedirectRequest *redirect_request; + redirect_request = + lasso_extract_gobject_from_list( + LassoIdWsf2Sb2RedirectRequest, + LASSO_TYPE_IDWSF2_SB2_REDIRECT_REQUEST, + fault->Detail->any); + if (redirect_request) { + lasso_assign_string(profile->parent.msg_url, redirect_request->redirectURL); + return LASSO_WSF_PROFILE_ERROR_REDIRECT_REQUEST; + } + return LASSO_WSF_PROFILE_ERROR_SOAP_FAULT; + + } + } + +cleanup: + return rc; } /** @@ -196,12 +560,13 @@ lasso_idwsf2_profile_process_soap_response_msg(LassoIdWsf2Profile *profile, cons * * Return the last parsed SOAP request object. * - * Return value: a #LassoSoapEnvelope object or NULL if no request as ever been parsed with this - * object. You must free this object. + * Return value:(transfer none): a #LassoSoapEnvelope object or NULL if no request as ever been + * parsed with this object. You must free this object. */ -LassoSoapEnvelope* lasso_idwsf2_profile_get_soap_envelope_request(LassoIdWsf2Profile *idwsf2_profile) +LassoSoapEnvelope* +lasso_idwsf2_profile_get_soap_envelope_request(LassoIdWsf2Profile *idwsf2_profile) { - return g_object_ref(idwsf2_profile->soap_envelope_request); + return _get_soap_envelope_request(idwsf2_profile); } @@ -211,59 +576,133 @@ LassoSoapEnvelope* lasso_idwsf2_profile_get_soap_envelope_request(LassoIdWsf2Pro * * Return the last parsed SOAP response object. * - * Return value: a #LassoSoapEnvelope object or NULL if no response as ever been parsed with this - * object. You must free this object. + * Return value:(transfer none): a #LassoSoapEnvelope object or NULL if no response as ever been + * parsed with this objects. You must free this object. */ -LassoSoapEnvelope* lasso_idwsf2_profile_get_soap_envelope_response(LassoIdWsf2Profile *idwsf2_profile) +LassoSoapEnvelope* +lasso_idwsf2_profile_get_soap_envelope_response(LassoIdWsf2Profile *idwsf2_profile) { - return g_object_ref(idwsf2_profile->soap_envelope_response); + return _get_soap_envelope_response(idwsf2_profile); } /** - * lasso_idwsf2_profile_set_response: + * lasso_idwsf2_profile_get_name_identifier: * @idwsf2_profile: a #LassoIdWsf2Profile object - * @response: (transfer full) (allow-none): a #LassoNode to set as the new content of the SOAP - * response * - * Replace the current content of the response with node. + * Return the NameIdentifier found in a WS-Security authentication token, when Bearer or SAML + * security mechanism is used. * + * Return value: (allow-none): a #LassoNode object or NULL. */ -void -lasso_idwsf2_profile_set_response(LassoIdWsf2Profile *idwsf2_profile, LassoNode *response) +LassoNode * +lasso_idwsf2_profile_get_name_identifier(LassoIdWsf2Profile *idwsf2_profile) { - if (! LASSO_IDWSF2_PROFILE(idwsf2_profile) || !idwsf2_profile->soap_envelope_response || - ! idwsf2_profile->soap_envelope_response->Body) - return; - lasso_assign_new_gobject(((LassoProfile*)idwsf2_profile)->response, response); - lasso_release_list_of_gobjects(idwsf2_profile->soap_envelope_response->Body->any); - lasso_list_add_gobject(idwsf2_profile->soap_envelope_response->Body->any, response); - return; + LassoSaml2Assertion *assertion = NULL; + LassoSaml2NameID *nameID = NULL; + LassoIdWsf2Sb2TargetIdentity *target_identity = NULL; + LassoSaml2EncryptedElement *encryptedID = NULL; + + + if (! LASSO_IS_IDWSF2_PROFILE(idwsf2_profile)) + return NULL; + + /** Already extracted, return it */ + if (idwsf2_profile->parent.nameIdentifier != NULL) + goto cleanup; + + /* Try to get a SAML2 assertion */ + assertion = lasso_soap_envelope_get_saml2_security_token + (lasso_idwsf2_profile_get_soap_envelope_request(idwsf2_profile)); + if (assertion && assertion->Subject) { + + /* We need a server object to check for audience and decrypt encrypted NameIDs */ + if (! LASSO_IS_SERVER(idwsf2_profile->parent.server)) { + goto cleanup; + } + + /* Check validity of the assertion */ + /* FIXME: get tolerance from profile */ + if (lasso_saml2_assertion_validate_conditions(assertion, + idwsf2_profile->parent.server->parent.ProviderID) != + LASSO_SAML2_ASSERTION_VALID) { + goto cleanup; + } + + lasso_assign_gobject (nameID, assertion->Subject->NameID); + lasso_assign_gobject (encryptedID, assertion->Subject->EncryptedID); + } + if (!nameID && !encryptedID) { + GList *it; + /* Go look at the target identity */ + target_identity = lasso_soap_envelope_sb2_get_target_identity_header ( + lasso_idwsf2_profile_get_soap_envelope_request (idwsf2_profile)); + if (target_identity) { + lasso_foreach (it, target_identity->any) + { + if (LASSO_IS_SAML2_NAME_ID(it->data)) { + lasso_assign_gobject (nameID, it->data); + break; + } + if (LASSO_IS_SAML2_ENCRYPTED_ELEMENT(it->data)) { + lasso_assign_gobject (encryptedID, it->data); + break; + } + } + } + + } + + if (lasso_saml20_profile_process_name_identifier_decryption(&idwsf2_profile->parent, &nameID, + &encryptedID) != 0) { + g_warning("process_name_identifier_decryption failed "\ + "when retrieving name identifier for ID-WSF profile"); + } + if (nameID) { + goto cleanup; + } + +cleanup: + lasso_release_gobject (assertion); + lasso_release_gobject (encryptedID); + lasso_assign_gobject (idwsf2_profile->parent.nameIdentifier, nameID); + return (LassoNode*)nameID; } /** - * lasso_idwsf2_profile_set_request: + * lasso_idwsf2_profile_get_epr: * @idwsf2_profile: a #LassoIdWsf2Profile object - * @request: (transfer full) (allow-none): a #LassoNode to set as the new content of the SOAP - * request. + * @epr: a #LassoWsAddrEndpointReference object * - * Replace the current content of the request with node. + * Set the EPR for the service targeted by the profile object. * */ void -lasso_idwsf2_profile_set_request(LassoIdWsf2Profile *idwsf2_profile, LassoNode *request) +lasso_idwsf2_profile_set_epr(LassoIdWsf2Profile *idwsf2_profile, + LassoWsAddrEndpointReference *epr) { - if (! LASSO_IDWSF2_PROFILE(idwsf2_profile) || !idwsf2_profile->soap_envelope_request || - ! idwsf2_profile->soap_envelope_request->Body) + if (! LASSO_IS_IDWSF2_PROFILE(idwsf2_profile) || ! LASSO_IS_WSA_ENDPOINT_REFERENCE(epr) || + ! idwsf2_profile->private_data) return; - lasso_assign_new_gobject(((LassoProfile*)idwsf2_profile)->request, request); - lasso_release_list_of_gobjects(idwsf2_profile->soap_envelope_request->Body->any); - lasso_list_add_gobject(idwsf2_profile->soap_envelope_request->Body->any, request); - return; + _set_epr(idwsf2_profile, epr); } -/*****************************************************************************/ -/* overridden parent class methods */ -/*****************************************************************************/ + +/** + * lasso_idwsf2_profile_get_epr: + * @idwsf2_profile: a #LassoIdWsf2Profile object + * + * Return the EPR used by this profile. + * + * Return value:(transfer none): a #LassoWsAddrEndpointReference object, or NULL if none is set. + */ +LassoWsAddrEndpointReference* +lasso_idwsf2_profile_get_epr(LassoIdWsf2Profile *idwsf2_profile) +{ + if (! LASSO_IS_IDWSF2_PROFILE(idwsf2_profile) || ! idwsf2_profile->private_data) + return NULL; + return _get_epr(idwsf2_profile); +} + static LassoNodeClass *parent_class = NULL; @@ -272,21 +711,16 @@ dispose(GObject *object) { LassoIdWsf2Profile *profile = LASSO_IDWSF2_PROFILE(object); - lasso_release_gobject(profile->soap_envelope_request); - lasso_release_gobject(profile->soap_envelope_response); + lasso_release_gobject(profile->private_data->soap_envelope_request); + lasso_release_gobject(profile->private_data->soap_envelope_response); G_OBJECT_CLASS(parent_class)->dispose(object); } -/*****************************************************************************/ -/* instance and class init functions */ -/*****************************************************************************/ - static void -instance_init(LassoIdWsf2Profile *profile) +instance_init(LassoIdWsf2Profile *discovery) { - profile->soap_envelope_request = NULL; - profile->soap_envelope_response = NULL; + discovery->private_data = g_new0(LassoIdWsf2ProfilePrivate, 1); } static void |