blob: 9aa93c2c635c13f647f87f53b3c89898dc846613 [file] [log] [blame]
/*
* Copyright 2003-2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <axis2_util.h>
#include <rampart_saml.h>
#include <oxs_constants.h>
#include <rp_property.h>
#include <oxs_xml_signature.h>
#include <oxs_transform.h>
#include <oxs_utility.h>
#include <oxs_transforms_factory.h>
#include <rp_includes.h>
#include <rp_secpolicy.h>
oxs_sign_part_t * AXIS2_CALL
rampart_saml_token_create_sign_part(const axutil_env_t *env,
rampart_context_t *rampart_context,
rampart_saml_token_t *saml,
axiom_node_t *str);
AXIS2_EXTERN axis2_status_t AXIS2_CALL
rampart_saml_token_validate(const axutil_env_t *env,
rampart_context_t *rampart_context,
axiom_node_t *assertion);
AXIS2_EXTERN axis2_status_t AXIS2_CALL
rampart_saml_supporting_token_build(const axutil_env_t *env,
rampart_context_t *rampart_context,
axiom_node_t *sec_node,
axutil_array_list_t *sign_parts)
{
axiom_node_t *strn = NULL, *assertion = NULL;
oxs_sign_part_t *sign_part = NULL;
rampart_saml_token_t *saml = rampart_context_get_saml_token(rampart_context, env, RAMPART_ST_TYPE_SIGNED_SUPPORTING_TOKEN);
if (!saml)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rs] SAML token not set in the rampart context. ERROR");
return AXIS2_FAILURE;
}
assertion = rampart_saml_token_get_assertion(saml, env);
if (!assertion)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rs] SAML assertion not set in the rampart_saml_token. ERROR");
return AXIS2_FAILURE;
}
axiom_node_add_child(sec_node, env, assertion);
strn = rampart_saml_token_get_str(saml, env);
if (!strn)
{
strn = oxs_saml_token_build_key_identifier_reference_local(env, NULL, assertion);
/*rampart_saml_token_set_str(saml, env, strn);*/
}
axiom_node_add_child(sec_node, env, strn);
sign_part = rampart_saml_token_create_sign_part(env, rampart_context, saml, strn);
if (!sign_part)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rs] Sign part creation failed. ERROR");
return AXIS2_FAILURE;
}
axutil_array_list_add(sign_parts, env, sign_part);
return AXIS2_SUCCESS;
}
oxs_sign_part_t * AXIS2_CALL
rampart_saml_token_create_sign_part(const axutil_env_t *env,
rampart_context_t *rampart_context,
rampart_saml_token_t *saml,
axiom_node_t *strn)
{
axiom_element_t *stre = NULL;
/*axiom_node_t *strn = NULL;*/
axutil_qname_t *qname = NULL;
axis2_char_t *id = NULL;
oxs_sign_part_t *sign_part = NULL;
oxs_transform_t *tr = NULL;
axutil_array_list_t *tr_list = NULL;
axis2_char_t * digest_method = rampart_context_get_digest_mtd(rampart_context, env);
stre = axiom_node_get_data_element(strn, env);
qname = axutil_qname_create(env, OXS_NODE_SECURITY_TOKEN_REFRENCE, OXS_WSSE_XMLNS, NULL);
sign_part = oxs_sign_part_create(env);
tr_list = axutil_array_list_create(env, 0);
/* If ID is not present we add it */
id = axiom_element_get_attribute_value(stre, env, qname);
if (!id)
{
id = oxs_util_generate_id(env, (axis2_char_t*)OXS_SIG_ID);
oxs_axiom_add_attribute(env, strn,
RAMPART_WSU, RAMPART_WSU_XMLNS, OXS_ATTR_ID, id);
}
oxs_sign_part_set_id(sign_part, env, id);
tr = oxs_transforms_factory_produce_transform(env,
OXS_HREF_TRANSFORM_STR_TRANSFORM);
axutil_array_list_add(tr_list, env, tr);
oxs_sign_part_set_transforms(sign_part, env, tr_list);
/* Sign the assertion, not the securitytokenreference */
oxs_sign_part_set_node(sign_part, env, strn);
oxs_sign_part_set_digest_mtd(sign_part, env, digest_method);
axutil_qname_free(qname, env);
AXIS2_FREE(env->allocator, id);
return sign_part;
}
AXIS2_EXTERN axis2_status_t AXIS2_CALL
rampart_saml_token_validate(const axutil_env_t *env,
rampart_context_t *rampart_context,
axiom_node_t *assertion)
{
axis2_status_t status = AXIS2_FAILURE;
oxs_sign_ctx_t *sign_ctx = NULL;
oxs_x509_cert_t *certificate = NULL;
axiom_node_t *sig_node = NULL;
rp_rampart_config_t *rampart_config = NULL;
rp_secpolicy_t *secpolicy;
axis2_char_t *cert_file = NULL;
secpolicy = rampart_context_get_secpolicy(rampart_context, env);
if (!secpolicy)
{
return AXIS2_SUCCESS;
}
rampart_config = rp_secpolicy_get_rampart_config(secpolicy, env);
if(!rampart_config)
{
return AXIS2_SUCCESS;
}
/* Still we don't have a mechanism to get the SAML signing key */
/* cert_file = rp_rampart_config_get_sts_certificate_file(rampart_config, env); */
if (!cert_file)
{
return AXIS2_SUCCESS;
}
certificate = oxs_key_mgr_load_x509_cert_from_pem_file(env, cert_file);
/* Need to get the certificate of the STS */
if (!certificate)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rs] Certificate cannot be found for the STS");
return AXIS2_FAILURE;
}
/*Create sign context*/
sign_ctx = oxs_sign_ctx_create(env);
/*Set the Certificate*/
oxs_sign_ctx_set_certificate(sign_ctx, env, certificate);
sig_node = oxs_axiom_get_node_by_local_name(env, assertion, OXS_NODE_SIGNATURE);
if (!sig_node)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rs] No Signature node in the SAML Assertion");
return AXIS2_FAILURE;
}
status = oxs_xml_sig_verify(env, sign_ctx, sig_node, assertion);
if (status == AXIS2_SUCCESS)
{
AXIS2_LOG_INFO(env->log, "SAML Signature Verification Successfull");
}
return status;
}
AXIS2_EXTERN rampart_saml_token_t * AXIS2_CALL
rampart_saml_add_token(rampart_context_t *rampart_context,
const axutil_env_t *env,
axiom_node_t *assertion,
axiom_node_t *str,
rampart_st_type_t type)
{
rampart_saml_token_t *saml = NULL;
rp_property_t *binding = NULL;
rp_secpolicy_t *secpolicy = NULL;
if (AXIS2_FAILURE == rampart_saml_token_validate(env, rampart_context, assertion))
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rs] SAML Signature Verification Failed");
return NULL;
}
if (type == RAMPART_ST_TYPE_SIGNED_SUPPORTING_TOKEN)
{
saml = rampart_saml_token_create(env, assertion, RAMPART_ST_CONFIR_TYPE_SENDER_VOUCHES);
rampart_saml_token_set_token_type(saml, env, RAMPART_ST_TYPE_SIGNED_SUPPORTING_TOKEN);
if (str)
rampart_saml_token_set_str(saml, env, str);
rampart_context_add_saml_token(rampart_context, env, saml);
return saml;
}
secpolicy = rampart_context_get_secpolicy(rampart_context, env);
binding = rp_secpolicy_get_binding(secpolicy,env);
if(rp_property_get_type(binding,env) == RP_PROPERTY_SYMMETRIC_BINDING)
{
rp_symmetric_binding_t *sym_binding = NULL;
sym_binding = (rp_symmetric_binding_t *)rp_property_get_value(binding,env);
if(sym_binding)
{
/*First check protection tokens have being specified.*/
if(rp_symmetric_binding_get_protection_token(sym_binding,env))
{
saml = rampart_context_get_saml_token(rampart_context, env, RAMPART_ST_TYPE_PROTECTION_TOKEN);
if (!saml)
{
saml = rampart_saml_token_create(env, assertion, RAMPART_ST_CONFIR_TYPE_HOLDER_OF_KEY);
rampart_saml_token_set_token_type(saml, env, RAMPART_ST_TYPE_PROTECTION_TOKEN);
if (str)
rampart_saml_token_set_str(saml, env, str);
rampart_context_add_saml_token(rampart_context, env, saml);
}
return saml;
}
else if (type == RAMPART_ST_TYPE_ENCRYPTION_TOKEN && rp_symmetric_binding_get_encryption_token(sym_binding,env))
{
saml = rampart_context_get_saml_token(rampart_context, env, RAMPART_ST_TYPE_ENCRYPTION_TOKEN);
if (!saml)
{
saml = rampart_saml_token_create(env, assertion, RAMPART_ST_CONFIR_TYPE_HOLDER_OF_KEY);
rampart_saml_token_set_token_type(saml, env, RAMPART_ST_TYPE_ENCRYPTION_TOKEN);
if (str)
rampart_saml_token_set_str(saml, env, str);
rampart_context_add_saml_token(rampart_context, env, saml);
}
return saml;
}
else if (type == RAMPART_ST_TYPE_SIGNATURE_TOKEN && rp_symmetric_binding_get_signature_token(sym_binding,env))
{
saml = rampart_context_get_saml_token(rampart_context, env, RAMPART_ST_TYPE_SIGNATURE_TOKEN);
if (!saml)
{
saml = rampart_saml_token_create(env, assertion, RAMPART_ST_CONFIR_TYPE_HOLDER_OF_KEY);
rampart_saml_token_set_token_type(saml, env, RAMPART_ST_TYPE_SIGNATURE_TOKEN);
if (str)
rampart_saml_token_set_str(saml, env, str);
rampart_context_add_saml_token(rampart_context, env, saml);
}
return saml;
}
}
else
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rs] SAML tokens as protection tokens, supported only in symmetric binding");
return NULL;
}
}
return NULL;
}
AXIS2_EXTERN char * AXIS2_CALL
rampart_saml_token_get_subject_confirmation(const axutil_env_t *env, axiom_node_t *assertion)
{
axiom_node_t *node = oxs_axiom_get_node_by_local_name(env, assertion, OXS_NODE_SAML_SUBJECT_CONFIRMATION_METHOD);
if (node)
{
return oxs_axiom_get_node_content(env, node);
}
return NULL;
}
/** Faults Defined by the specification **/
AXIS2_EXTERN int AXIS2_CALL
rampart_saml_token_fault_securitytokenunavailable(axutil_env_t *env,
axis2_msg_ctx_t *ctx)
{
axiom_soap_envelope_t *envelope = NULL;
int soap_version = AXIOM_SOAP12;
axutil_array_list_t *sub_codes = NULL;
sub_codes = axutil_array_list_create(env, 1);
axutil_array_list_add(sub_codes, env, axutil_strdup(env, RAMPART_ST_FAULT_SECURITYTOKENUNAVAILABLE_CODE));
envelope = axiom_soap_envelope_create_default_soap_fault_envelope(env,
RAMPART_SAML_FAULT_CODE,
RAMPART_ST_FAULT_SECURITYTOKENUNAVAILABLE_STR,
soap_version, sub_codes, NULL);
if (!envelope)
{
axutil_array_list_free(sub_codes, env);
return AXIS2_FAILURE;
}
axis2_msg_ctx_set_fault_soap_envelope(ctx, env, envelope);
axutil_array_list_free(sub_codes, env);
return AXIS2_SUCCESS;
}
AXIS2_EXTERN int AXIS2_CALL
rampart_saml_token_fault_unsupportedsecuritytoken(axutil_env_t *env,
axis2_msg_ctx_t *ctx)
{
axiom_soap_envelope_t *envelope = NULL;
int soap_version = AXIOM_SOAP12;
axutil_array_list_t *sub_codes = NULL;
sub_codes = axutil_array_list_create(env, 1);
axutil_array_list_add(sub_codes, env, axutil_strdup(env, RAMPART_ST_FAULT_UNSUPPORTEDSECURITYTOKEN_CODE));
envelope = axiom_soap_envelope_create_default_soap_fault_envelope(env,
RAMPART_SAML_FAULT_CODE,
RAMPART_ST_FAULT_UNSUPPORTEDSECURITYTOKEN_STR,
soap_version, sub_codes, NULL);
if (!envelope)
{
axutil_array_list_free(sub_codes, env);
return AXIS2_FAILURE;
}
axis2_msg_ctx_set_fault_soap_envelope(ctx, env, envelope);
axutil_array_list_free(sub_codes, env);
return AXIS2_SUCCESS;
}
AXIS2_EXTERN int AXIS2_CALL
rampart_saml_token_fault_failedcheck(axutil_env_t *env,
axis2_msg_ctx_t *ctx)
{
axiom_soap_envelope_t *envelope = NULL;
int soap_version = AXIOM_SOAP12;
axutil_array_list_t *sub_codes = NULL;
sub_codes = axutil_array_list_create(env, 1);
axutil_array_list_add(sub_codes, env, axutil_strdup(env, RAMPART_ST_FAULT_FAILEDCHECK_CODE));
envelope = axiom_soap_envelope_create_default_soap_fault_envelope(env,
RAMPART_SAML_FAULT_CODE,
RAMPART_ST_FAULT_FAILEDCHECK_STR,
soap_version, sub_codes, NULL);
if (!envelope)
{
axutil_array_list_free(sub_codes, env);
return AXIS2_FAILURE;
}
axis2_msg_ctx_set_fault_soap_envelope(ctx, env, envelope);
axutil_array_list_free(sub_codes, env);
return AXIS2_SUCCESS;
}
AXIS2_EXTERN int AXIS2_CALL
rampart_saml_token_fault_invalidsecuritytoken(axutil_env_t *env,
axis2_msg_ctx_t *ctx)
{
axiom_soap_envelope_t *envelope = NULL;
int soap_version = AXIOM_SOAP12;
axutil_array_list_t *sub_codes = NULL;
sub_codes = axutil_array_list_create(env, 1);
axutil_array_list_add(sub_codes, env, axutil_strdup(env, RAMPART_ST_FAULT_INVALIDSECURITYTOKEN_CODE));
envelope = axiom_soap_envelope_create_default_soap_fault_envelope(env,
RAMPART_SAML_FAULT_CODE,
RAMPART_ST_FAULT_INVALIDSECURITYTOKEN_STR,
soap_version, sub_codes, NULL);
if (!envelope)
{
axutil_array_list_free(sub_codes, env);
return AXIS2_FAILURE;
}
axis2_msg_ctx_set_fault_soap_envelope(ctx, env, envelope);
axutil_array_list_free(sub_codes, env);
return AXIS2_SUCCESS;
}