blob: 505e0949920a1a07d55fff6e89a1c7ef95978155 [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 <axutil_utils.h>
#include <oxs_ctx.h>
#include <oxs_error.h>
#include <oxs_utility.h>
#include <rampart_encryption.h>
#include <oxs_key.h>
#include <rampart_constants.h>
#include <rampart_handler_util.h>
#include <oxs_tokens.h>
#include <axutil_array_list.h>
#include <oxs_axiom.h>
#include <oxs_asym_ctx.h>
#include <oxs_xml_encryption.h>
#include <axis2_key_type.h>
/*Private functions*/
axis2_status_t AXIS2_CALL
rampart_enc_get_nodes_to_encrypt(
rampart_context_t *rampart_context,
const axutil_env_t *env,
axiom_soap_envelope_t *soap_envelope,
axutil_array_list_t *nodes_to_encrypt)
{
axis2_status_t status1 = AXIS2_SUCCESS;
axis2_status_t status2 = AXIS2_SUCCESS;
status1 = rampart_context_get_nodes_to_encrypt(rampart_context,env,soap_envelope,nodes_to_encrypt);
status2 = rampart_context_get_elements_to_encrypt(rampart_context,env,soap_envelope,nodes_to_encrypt);
if(status1 == AXIS2_SUCCESS || status2 == AXIS2_SUCCESS)
return AXIS2_SUCCESS;
else
return AXIS2_FAILURE;
}
/*Public functions*/
AXIS2_EXTERN axis2_status_t AXIS2_CALL
rampart_enc_encrypt_message(const axutil_env_t *env,
axis2_msg_ctx_t *msg_ctx,
rampart_context_t *rampart_context,
axiom_soap_envelope_t *soap_envelope,
axiom_node_t *sec_node)
{
axutil_array_list_t *nodes_to_encrypt = NULL;
axutil_array_list_t *id_list = NULL;
axis2_status_t status = AXIS2_FAILURE;
axis2_char_t *enc_sym_algo = NULL;
axis2_char_t *enc_asym_algo = NULL;
axis2_char_t *eki = NULL;
axis2_char_t *certificate_file = NULL;
axis2_char_t *password = NULL;
oxs_key_t *session_key = NULL;
oxs_asym_ctx_t *asym_ctx = NULL;
axis2_bool_t server_side = AXIS2_FALSE;
int token_type = 0;
rp_property_t *token = NULL;
axis2_char_t *enc_user = NULL;
rampart_callback_t *password_callback = NULL;
password_callback_fn password_function = NULL;
void *param = NULL;
void *key_buf = NULL;
int i = 0;
/*Get nodes to be encrypted*/
server_side = axis2_msg_ctx_get_server_side(msg_ctx,env);
nodes_to_encrypt = axutil_array_list_create(env,0);
/*status = rampart_context_get_nodes_to_encrypt(rampart_context,env,soap_envelope,nodes_to_encrypt);*/
status = rampart_enc_get_nodes_to_encrypt(rampart_context,env,soap_envelope,nodes_to_encrypt);
if((status!=AXIS2_SUCCESS)||(axutil_array_list_size(nodes_to_encrypt,env)==0))
{
AXIS2_LOG_INFO(env->log, "[rampart][rampart_encryption] No parts specified or specified parts can't be found for encryprion.");
return AXIS2_SUCCESS;
}
/*Now we have to check whether a token is specified.*/
token = rampart_context_get_token(rampart_context,env,AXIS2_TRUE,server_side);
if(!token)
{
AXIS2_LOG_INFO(env->log,"[rampart][rampart_encryption] Encryption Token is not specified");
return AXIS2_SUCCESS;
}
token_type = rp_property_get_type(token,env);
if(!rampart_context_is_token_type_supported(token_type,env))
return AXIS2_FAILURE;
if(rampart_context_check_is_derived_keys(env,token))
{
AXIS2_LOG_INFO(env->log,"[rampart][rampart_encryption] We still do not support derived keys");
return AXIS2_FAILURE;
}
/*Get the symmetric encryption algorithm*/
enc_sym_algo = rampart_context_get_enc_sym_algo(rampart_context,env);
/*If not specified set the default*/
if(!enc_sym_algo || (0 == axutil_strcmp(enc_sym_algo, ""))){
AXIS2_LOG_INFO(env->log, "[rampart][rampart_encryption] No symmetric algorithm is specified for encryption. Using the default");
enc_sym_algo = OXS_DEFAULT_SYM_ALGO;
}
/*Generate the session key*/
session_key = oxs_key_create(env);
status = oxs_key_for_algo(session_key, env, enc_sym_algo);
if(AXIS2_FAILURE == status){
return AXIS2_FAILURE;
}
/*Create a list to store EncDataIds. This will be used in building the ReferenceList*/
id_list = axutil_array_list_create(env, 5);
/*Repeat until all encryption parts are encrypted*/
for(i=0 ; i < axutil_array_list_size(nodes_to_encrypt, env); i++){
axiom_node_t *node_to_enc = NULL;
axiom_node_t *parent_of_node_to_enc = NULL;
axiom_node_t *enc_data_node = NULL;
oxs_ctx_t *enc_ctx = NULL;
axis2_char_t *id = NULL;
axis2_status_t enc_status = AXIS2_FAILURE;
/*Get the node to be encrypted*/
node_to_enc = (axiom_node_t *)axutil_array_list_get(nodes_to_encrypt, env, i);
if(!node_to_enc){
return AXIS2_FAILURE;
}
/*Create the encryption context for OMXMLSEC*/
enc_ctx = oxs_ctx_create(env);
/*Set the key*/
oxs_ctx_set_key(enc_ctx, env, session_key);
/*Set the algorithm*/
oxs_ctx_set_enc_mtd_algorithm(enc_ctx, env, enc_sym_algo);
/*Create an empty EncryptedDataNode*/
parent_of_node_to_enc = axiom_node_get_parent(node_to_enc, env);
id = oxs_util_generate_id(env,(axis2_char_t*)OXS_ENCDATA_ID);
enc_data_node = oxs_token_build_encrypted_data_element(env, parent_of_node_to_enc, OXS_TYPE_ENC_ELEMENT, id );
enc_status = oxs_xml_enc_encrypt_node(env, enc_ctx, node_to_enc, &enc_data_node);
axutil_array_list_add(id_list, env, id);
if(AXIS2_FAILURE == enc_status){
return AXIS2_FAILURE;
}
}
/*Get the asymmetric key encryption algorithm*/
enc_asym_algo = rampart_context_get_enc_asym_algo(rampart_context,env);
/*Get encryption key identifier*/
/*First we should check whether we include the token in the
*message.*/
if(rampart_context_is_token_include(rampart_context,token,token_type,server_side,env))
{
eki = RAMPART_STR_DIRECT_REFERENCE;
}
else
{
eki = rampart_context_get_key_identifier(rampart_context,token,env);
}
if(!eki)
{
AXIS2_LOG_INFO(env->log, "[rampart][rampart_encryption] No mechanism for attaching the token.");
return AXIS2_FAILURE;
}
/*Create asymmetric encryption context*/
asym_ctx = oxs_asym_ctx_create(env);
oxs_asym_ctx_set_algorithm(asym_ctx, env, enc_asym_algo);
/*First check whether the public key is set*/
key_buf = rampart_context_get_receiver_certificate(rampart_context,env);
if(key_buf)
{
axis2_key_type_t type = 0;
type = rampart_context_get_receiver_certificate_type(rampart_context,env);
if(type == AXIS2_KEY_TYPE_PEM)
{
oxs_asym_ctx_set_format(asym_ctx, env, OXS_ASYM_CTX_FORMAT_PEM);
oxs_asym_ctx_set_pem_buf(asym_ctx, env, (axis2_char_t *)key_buf);
}
}
/*Buffer is null load from the file*/
else
{
certificate_file = rampart_context_get_receiver_certificate_file(rampart_context,env);
oxs_asym_ctx_set_file_name(asym_ctx, env, certificate_file);
oxs_asym_ctx_set_format(asym_ctx, env, oxs_util_get_format_by_file_extension(env, certificate_file));
/*Get the password to retrieve the key from key store*/
password = rampart_context_get_prv_key_password(rampart_context,env);
if(!password)
{
enc_user = rampart_context_get_encryption_user(rampart_context,env);
if(!enc_user)
enc_user = rampart_context_get_user(rampart_context,env);
if(enc_user)
{
password_function = rampart_context_get_pwcb_function(rampart_context,env);
if(password_function)
password = (*password_function)(env,enc_user,param);
else
{
password_callback = rampart_context_get_password_callback(rampart_context,env);
if(!password_callback)
{
AXIS2_LOG_INFO(env->log, "[rampart][rampart_encryption] Password call back module is not loaded.");
return AXIS2_FAILURE;
}
password = rampart_callback_password(env, password_callback, enc_user);
if(password)
oxs_asym_ctx_set_password(asym_ctx, env, password);
}
}
}
}
oxs_asym_ctx_set_operation(asym_ctx, env, OXS_ASYM_CTX_OPERATION_PUB_ENCRYPT);
oxs_asym_ctx_set_st_ref_pattern(asym_ctx, env, eki);
/*Encrypt the session key*/
status = oxs_xml_enc_encrypt_key(env, asym_ctx, sec_node, session_key, id_list);
if(AXIS2_FAILURE == status){
return AXIS2_FAILURE;
}
return AXIS2_SUCCESS;
}