blob: 1c0f3428aead512414c770f8df7f62125584940a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 <stdio.h>
#include <rampart_encryption.h>
#include <rampart_constants.h>
#include <rampart_sec_header_builder.h>
#include <rampart_username_token.h>
#include <rampart_timestamp_token.h>
#include <rampart_util.h>
#include <rampart_sec_processed_result.h>
#include <rampart_handler_util.h>
#include <oxs_error.h>
#include <oxs_utility.h>
#include <oxs_key.h>
#include <oxs_axiom.h>
#include <oxs_asym_ctx.h>
#include <oxs_tokens.h>
#include <axutil_utils.h>
#include <axutil_array_list.h>
#include <rampart_signature.h>
/*Private functions*/
axis2_status_t AXIS2_CALL
rampart_interchange_nodes(const axutil_env_t *env,
axiom_node_t *node_to_move,
axiom_node_t *node_before)
{
axis2_status_t status = AXIS2_FAILURE;
axiom_node_t *temp_node = NULL;
temp_node = axiom_node_detach(node_to_move,env);
status = axiom_node_insert_sibling_before(node_before,env,temp_node);
return status;
}
/*Public functions*/
AXIS2_EXTERN axis2_status_t AXIS2_CALL
rampart_shb_build_message(
const axutil_env_t *env,
axis2_msg_ctx_t *msg_ctx,
rampart_context_t *rampart_context,
axiom_soap_envelope_t *soap_envelope)
{
axis2_status_t status = AXIS2_SUCCESS;
axiom_soap_header_t *soap_header = NULL;
axiom_node_t *soap_header_node = NULL;
axiom_element_t *soap_header_ele = NULL;
axiom_soap_header_block_t *sec_header_block = NULL;
axiom_namespace_t *sec_ns_obj = NULL;
axiom_node_t *sec_node = NULL;
axiom_element_t *sec_ele = NULL;
axis2_bool_t is_encrypt_before_sign = AXIS2_FALSE;
axis2_bool_t signature_protection = AXIS2_FALSE;
axiom_node_t *sig_node = NULL;
axiom_node_t *enc_key_node = NULL;
AXIS2_ENV_CHECK(env,AXIS2_FAILURE);
soap_header = axiom_soap_envelope_get_header(soap_envelope, env);
soap_header_node = axiom_soap_header_get_base_node(soap_header, env);
soap_header_ele = (axiom_element_t *)axiom_node_get_data_element(
soap_header_node, env);
sec_ns_obj = axiom_namespace_create(env, RAMPART_WSSE_XMLNS,
RAMPART_WSSE);
sec_header_block = axiom_soap_header_add_header_block(soap_header,
env, RAMPART_SECURITY, sec_ns_obj);
if(!sec_header_block)
{
AXIS2_LOG_INFO(env->log, "[rampart][shb] Security header block is NULL");
return AXIS2_SUCCESS;
}
axiom_soap_header_block_set_must_understand_with_bool(sec_header_block,
env, AXIS2_TRUE);
sec_node = axiom_soap_header_block_get_base_node(sec_header_block, env);
sec_ele = (axiom_element_t *)
axiom_node_get_data_element(sec_node, env);
/*check the binding*/
if((rampart_context_get_binding_type(rampart_context,env)) == RP_PROPERTY_ASYMMETRIC_BINDING)
{
/*Do Asymmetric Binding specific things*/
AXIS2_LOG_INFO(env->log, "[rampart][shb] Using asymmetric binding");
/*Timestamp Inclusion*/
if(rampart_context_is_include_timestamp(rampart_context,env))
{
int ttl = -1;
AXIS2_LOG_INFO(env->log, "[rampart][shb] building Timestamp Token");
AXIS2_LOG_INFO(env->log, "[rampart][shb] Using default timeToLive value %d",
RAMPART_TIMESTAMP_TOKEN_DEFAULT_TIME_TO_LIVE);
/*ttl = RAMPART_TIMESTAMP_TOKEN_DEFAULT_TIME_TO_LIVE;*/
ttl = rampart_context_get_ttl(rampart_context,env);
status = rampart_timestamp_token_build(env,
sec_node, sec_ns_obj, ttl);
if (status == AXIS2_FAILURE)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] Timestamp Token build failed. ERROR");
return AXIS2_FAILURE;
}
}
/*Check whether we need username token*/
/*User name tokens includes in messages sent from client to server*/
if(!axis2_msg_ctx_get_server_side(msg_ctx,env))
{
if(rampart_context_is_include_username_token(rampart_context,env))
{
/*Now we are passing rampart_context here so inside this method
relevant parameters are extracted. */
AXIS2_LOG_INFO(env->log, "[rampart][shb] building UsernmaeToken");
status =rampart_username_token_build(
env,
rampart_context,
sec_node,
sec_ns_obj);
if (status == AXIS2_FAILURE)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] UsernmaeToken build failed. ERROR");
return AXIS2_FAILURE;
}
}
}
signature_protection = rampart_context_is_encrypt_signature(rampart_context, env);
/*Check the encryption and signature order*/
if(rampart_context_is_encrypt_before_sign(rampart_context, env))
{
is_encrypt_before_sign = AXIS2_TRUE;
/*If signature_protection=> <sp:EncryptSignature/> is ON*/
if(signature_protection)
{
/*First Encrypt the parts specified in encrypted parts*/
status = rampart_enc_encrypt_message(env, msg_ctx, rampart_context, soap_envelope, sec_node);
if(status != AXIS2_SUCCESS)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] Encryption failed. ERROR");
return AXIS2_FAILURE;
}
/*Add a key reference in Encrypted Data in the Body*/
status = rampart_enc_add_key_info(env, msg_ctx, rampart_context, soap_envelope, sec_node);
if(status != AXIS2_SUCCESS)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] Cannot add Key information");
return AXIS2_FAILURE;
}
/*Then Sign the message*/
status = rampart_sig_sign_message(env, msg_ctx, rampart_context, soap_envelope, sec_node);
if(status != AXIS2_SUCCESS)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] Signing failed. ERROR");
return AXIS2_FAILURE;
}
/*Then encrypt the signature */
status = rampart_enc_encrypt_signature(env, msg_ctx, rampart_context, soap_envelope, sec_node);
if(status != AXIS2_SUCCESS)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] Encrypt signature failed. ERROR");
return AXIS2_FAILURE;
}
}
else
{
status = rampart_enc_encrypt_message(env, msg_ctx, rampart_context, soap_envelope, sec_node);
if(status != AXIS2_SUCCESS){
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] Encryption failed. ERROR");
return AXIS2_FAILURE;
}
/*Then do signature specific things*/
status = rampart_sig_sign_message(env, msg_ctx, rampart_context, soap_envelope, sec_node);
if(status != AXIS2_SUCCESS){
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] Signature failed. ERROR");
return AXIS2_FAILURE;
}
}
/*Then Handle Supporting token stuff */
}
else
{
is_encrypt_before_sign = AXIS2_FALSE;
/*First do signature specific stuff*/
status = rampart_sig_sign_message(env, msg_ctx, rampart_context, soap_envelope, sec_node);
if(status != AXIS2_SUCCESS){
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] Signing failed. ERROR");
return AXIS2_FAILURE;
}
/*Then Handle Encryption stuff*/
status = rampart_enc_encrypt_message(env, msg_ctx, rampart_context, soap_envelope, sec_node);
if(status!=AXIS2_SUCCESS ){
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][shb] Encryption failed. ERROR");
return AXIS2_FAILURE;
}
}
/*If both encryption and signature is done we should interchange them.
* because the action done last should appear first in the header. */
sig_node = oxs_axiom_get_node_by_local_name(env,sec_node,OXS_NODE_SIGNATURE);
enc_key_node = oxs_axiom_get_node_by_local_name(env,sec_node,OXS_NODE_ENCRYPTED_KEY);
if(sig_node && enc_key_node)
{
if(is_encrypt_before_sign)
{
status = rampart_interchange_nodes(env, sig_node, enc_key_node);
if(status!=AXIS2_SUCCESS)
{
AXIS2_LOG_INFO(env->log,"[rampart][shb]Node interchange failed.");
return status;
}
}
else
{
status = rampart_interchange_nodes(env, enc_key_node, sig_node);
if(status!=AXIS2_SUCCESS)
{
AXIS2_LOG_INFO(env->log,"[rampart][shb]Node interchange failed.");
return status;
}
}
}
else if(enc_key_node && signature_protection)
{
if(!is_encrypt_before_sign)
{
axiom_node_t *enc_data_node = NULL;
enc_data_node = oxs_axiom_get_node_by_local_name(env, sec_node, OXS_NODE_ENCRYPTED_DATA);
if(!enc_data_node)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,"[rampart][shb]Signature is not encrypted,");
return AXIS2_FAILURE;
}
else
{
status = rampart_interchange_nodes(env, enc_key_node, enc_data_node);
if(status != AXIS2_SUCCESS)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,"[rampart][shb]Cannot interchange enc_key and enc_data nodes");
return AXIS2_FAILURE;
}
}
}
}
return AXIS2_SUCCESS;
}
else if((rampart_context_get_binding_type(rampart_context,env)) == RP_PROPERTY_SYMMETRIC_BINDING)
{
/*Do Symmetric_binding specific things*/
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[rampart][shb] Symmetric Binding. We do not support yet");
return AXIS2_FAILURE;
}
else if((rampart_context_get_binding_type(rampart_context,env)) == RP_PROPERTY_TRANSPORT_BINDING)
{
AXIS2_LOG_INFO(env->log, "[rampart][shb] Using transport binding");
/*Timestamp Inclusion*/
if(rampart_context_is_include_timestamp(rampart_context,env))
{
int ttl = -1;
AXIS2_LOG_INFO(env->log, "[rampart][shb] building Timestamp Token");
AXIS2_LOG_INFO(env->log, "[rampart][shb] Using default timeToLive value %d",
RAMPART_TIMESTAMP_TOKEN_DEFAULT_TIME_TO_LIVE);
/*ttl = RAMPART_TIMESTAMP_TOKEN_DEFAULT_TIME_TO_LIVE;*/
ttl = rampart_context_get_ttl(rampart_context,env);
status = rampart_timestamp_token_build(env,
sec_node, sec_ns_obj, ttl);
if (status == AXIS2_FAILURE)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[rampart][shb] Timestamp Token build failed. ERROR");
return AXIS2_FAILURE;
}
}
/*Check whether we need username token*/
/*User name tokens includes in messages sent from client to server*/
if(!axis2_msg_ctx_get_server_side(msg_ctx,env))
{
if(rampart_context_is_include_username_token(rampart_context,env))
{
/*Now we are passing rampart_context here so inside this method
relevant parameters are extracted. */
AXIS2_LOG_INFO(env->log, "[rampart][shb] building UsernmaeToken");
status =rampart_username_token_build(
env,
rampart_context,
sec_node,
sec_ns_obj);
if (status == AXIS2_FAILURE)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[rampart][shb] UsernmaeToken build failed. ERROR");
return AXIS2_FAILURE;
}
}
return status;
}
return status;
}
else{
return AXIS2_FAILURE;
}
}