blob: d9b869c1849e863b24da03a70fa200b329d7c0b6 [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 <rampart_engine.h>
#include <axis2_ctx.h>
#include <axis2_svc.h>
#include <axis2_desc.h>
#include <axis2_policy_include.h>
#include <rp_secpolicy_builder.h>
#include <neethi_policy.h>
#include <rampart_authn_provider.h>
#include <rampart_util.h>
#include <rampart_constants.h>
#include <rampart_callback.h>
#include <axis2_msg.h>
#include <axis2_conf_ctx.h>
#include <rampart_handler_util.h>
#include <rampart_config.h>
#include <axis2_options.h>
#include <openssl_pkcs12_keystore.h>
#include <rampart_sct_provider_utility.h>
static neethi_policy_t *
rampart_engine_build_policy(
const axutil_env_t *env,
axis2_msg_ctx_t *msg_ctx,
axis2_bool_t is_inflow);
static axis2_status_t
rampart_engine_set_user_properties(
const axutil_env_t *env,
rampart_context_t *rampart_context);
static axis2_status_t
rampart_engine_retrieve_key_mgr_prop_from_policy(
rampart_context_t *rampart_context,
const axutil_env_t *env);
AXIS2_EXTERN rampart_context_t *AXIS2_CALL
rampart_engine_build_configuration(
const axutil_env_t *env,
axis2_msg_ctx_t *msg_ctx,
axis2_bool_t is_inflow)
{
rp_secpolicy_t *secpolicy = NULL;
rampart_context_t *rampart_context = NULL;
axis2_status_t status = AXIS2_SUCCESS;
axis2_bool_t is_server_side = AXIS2_TRUE;
neethi_policy_t *policy = NULL;
axutil_property_t *property = NULL;
void *value = NULL;
/* Key Manager related */
oxs_key_mgr_t *key_mgr = NULL;
axis2_char_t *password = NULL;
axis2_char_t *enc_user = NULL;
axis2_char_t *pkcs12_file = NULL;
axis2_char_t *pkcs12_password = NULL;
axis2_char_t *pkcs12_buf = NULL;
password_callback_fn password_function = NULL;
rampart_callback_t *password_callback = NULL;
pkcs12_keystore_t *key_store = NULL;
is_server_side = axis2_msg_ctx_get_server_side(msg_ctx, env);
/*policy has to be created for inflow and outflow for server side.
but for client side, it will be created only on outflow*/
if(is_server_side || (!is_server_side && !is_inflow))
{
policy = rampart_engine_build_policy(env, msg_ctx, is_inflow);
if(!policy)
{
rampart_create_fault_envelope(env, RAMPART_FAULT_FAILED_CHECK,
"Error in the Internal configuration.", RAMPART_FAULT_IN_POLICY, msg_ctx);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rampart_engine] Policy creation failed.");
return NULL;
}
}
/* for server side's outflow and client side's inflow, we have to use rampart context
* created in server side's inflow or client side's out flow
*/
if((is_server_side && !is_inflow) || (!is_server_side && is_inflow))
{
if(is_server_side)
{
property = axis2_msg_ctx_get_property(msg_ctx, env, RAMPART_CONTEXT);
}
else
{
/* Options from client's out message context will not be copied to in message context.
* So, we have to get original out message context to access the property
*/
axis2_op_ctx_t *op_ctx = NULL;
op_ctx = axis2_msg_ctx_get_op_ctx(msg_ctx, env);
if(op_ctx)
{
axis2_msg_ctx_t *out_msg_ctx = NULL;
out_msg_ctx = axis2_op_ctx_get_msg_ctx(op_ctx, env, AXIS2_WSDL_MESSAGE_LABEL_OUT);
if(out_msg_ctx)
{
property = axis2_msg_ctx_get_property(out_msg_ctx, env, RAMPART_CONTEXT);
}
}
}
if(property)
{
rampart_context = (rampart_context_t *)axutil_property_get_value(property, env);
/*for serverside, recreate security policy and attach it to rampart context. This is because,
there might be differnt policy for inflow and outflow (only for server side. we are still not
supporting this feature for client side*/
if(is_server_side)
{
secpolicy = rp_secpolicy_builder_build(env, policy);
if(!secpolicy)
{
rampart_create_fault_envelope(env, RAMPART_FAULT_FAILED_CHECK,
"Error in the Internal security policy configuration.",
RAMPART_FAULT_IN_POLICY, msg_ctx);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rampart_engine] Cannot create security policy from policy.");
return NULL;
}
rampart_context_set_secpolicy(rampart_context, env, secpolicy);
}
return (rampart_context_t *)axutil_property_get_value(property, env);
}
else
{
rampart_create_fault_envelope(env, RAMPART_FAULT_FAILED_CHECK,
"Error in the Internal security policy configuration.", RAMPART_FAULT_IN_POLICY,
msg_ctx);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rampart_engine] Cannot get saved rampart_context");
return NULL;
}
}
/*rampart context will be created for server side's inflow and client side's out flow*/
value = rampart_get_rampart_configuration(env, msg_ctx, RAMPART_CONFIGURATION);
if(value)
{
rampart_context = (rampart_context_t *)value;
rampart_context_increment_ref(rampart_context, env);
if(!rampart_context_get_secpolicy(rampart_context, env))
{
secpolicy = rp_secpolicy_builder_build(env, policy);
if(!secpolicy)
{
rampart_create_fault_envelope(env, RAMPART_FAULT_FAILED_CHECK,
"Error in the Internal security policy configuration.",
RAMPART_FAULT_IN_POLICY, msg_ctx);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rampart_engine] Cannot create security policy from policy.");
return NULL;
}
rampart_context_set_secpolicy(rampart_context, env, secpolicy);
}
}
else
{
rampart_context = rampart_context_create(env);
secpolicy = rp_secpolicy_builder_build(env, policy);
if(!secpolicy)
{
rampart_create_fault_envelope(env, RAMPART_FAULT_FAILED_CHECK,
"Error in the Internal configuration.", RAMPART_FAULT_IN_POLICY, msg_ctx);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rampart_engine] Cannot create security policy from policy.");
rampart_context_free(rampart_context, env);
rampart_context = NULL;
return NULL;
}
rampart_context_set_secpolicy(rampart_context, env, secpolicy);
status = rampart_engine_set_user_properties(env, rampart_context);
if(status != AXIS2_SUCCESS)
{
rampart_create_fault_envelope(env, RAMPART_FAULT_FAILED_CHECK,
"Error in the Internal configuration.", RAMPART_FAULT_IN_POLICY, msg_ctx);
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rampart_engine] rampc policies creation failed.");
rampart_context_free(rampart_context, env);
rampart_context = NULL;
return NULL;
}
rampart_engine_retrieve_key_mgr_prop_from_policy(rampart_context, env);
}
key_mgr = rampart_context_get_key_mgr(rampart_context, env);
if(!key_mgr)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[rampart][engine] Key mgr creation failed.");
return NULL;
}
/* Retrieve the password for obtaining private keys */
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)
{
void *param = NULL;
param = rampart_context_get_pwcb_user_params(rampart_context, env);
password = (*password_function)(env, enc_user, param);
pkcs12_password = password;
}
else
{
password_callback = rampart_context_get_password_callback(rampart_context, env);
if(password_callback)
{
password = rampart_callback_password(env, password_callback, enc_user);
pkcs12_password
= rampart_callback_pkcs12_password(env, password_callback, enc_user);
}
else
{
password = rampart_context_get_password(rampart_context, env);
pkcs12_password = password;
}
}
}
pkcs12_file = rampart_context_get_pkcs12_file_name(rampart_context, env);
if(pkcs12_file && pkcs12_password)
{
key_store = pkcs12_keystore_create(env, pkcs12_file, pkcs12_password);
if(!key_store)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][engine] PKCS12 KeyStore creation failed.");
return NULL;
}
}
else if(pkcs12_password && (pkcs12_buf = (axis2_char_t*)rampart_context_get_key_store_buff(
rampart_context, env)))
{
key_store = pkcs12_keystore_create_from_buffer(env, pkcs12_buf, password,
oxs_key_mgr_get_key_store_buff_len(key_mgr, env));
if(!key_store)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][engine] PKCS12 KeyStore creation failed.");
return NULL;
}
}
oxs_key_mgr_set_key_store(key_mgr, env, key_store);
if(password)
{
oxs_key_mgr_set_prv_key_password(key_mgr, env, password);
}
/* Since rampart_context is for request scope, we have to store in a container which has
* request scope
*/
property = axutil_property_create_with_args(env, AXIS2_SCOPE_REQUEST, AXIS2_TRUE,
(void *)rampart_context_free, rampart_context);
axis2_msg_ctx_set_property(msg_ctx, env, RAMPART_CONTEXT, property);
/*For the client side*/
if(!is_server_side)
{
value = axis2_msg_ctx_get_property_value(msg_ctx, env, RAMPART_CLIENT_CONFIGURATION);
if(value)
{
rampart_config_t *client_config = NULL;
axutil_array_list_t *saml_tokens = NULL;
axis2_char_t *config_value = NULL;
issued_token_callback_func issued_token_aquire = NULL;
int ttl = 0;
client_config = (rampart_config_t*)value;
config_value = rampart_config_get_username(client_config, env);
if(config_value)
{
rampart_context_set_user(rampart_context, env, config_value);
}
config_value = rampart_config_get_password(client_config, env);
if(config_value)
{
rampart_context_set_password(rampart_context, env, config_value);
}
config_value = rampart_config_get_password_type(client_config, env);
if(config_value)
{
rampart_context_set_password_type(rampart_context, env, config_value);
}
ttl = rampart_config_get_ttl(client_config, env);
if(ttl > 0)
{
rampart_context_set_ttl(rampart_context, env, ttl);
}
saml_tokens = rampart_config_get_saml_tokens(client_config, env);
if(saml_tokens)
{
rampart_context_set_saml_tokens(rampart_context, env, saml_tokens);
}
issued_token_aquire = rampart_config_get_issued_token_aquire_function(client_config,
env);
if(issued_token_aquire)
{
rampart_context_set_issued_token_aquire_function(rampart_context, env,
issued_token_aquire);
}
}
}
return rampart_context;
}
static neethi_policy_t*
rampart_engine_build_policy(
const axutil_env_t *env,
axis2_msg_ctx_t *msg_ctx,
axis2_bool_t is_inflow)
{
axis2_desc_t *desc = NULL;
axis2_policy_include_t *policy_include = NULL;
neethi_policy_t *service_policy = NULL;
axis2_op_t *op = NULL;
axis2_msg_t *msg = NULL;
op = axis2_msg_ctx_get_op(msg_ctx, env);
if(!op)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rampart_engine] Cannot find policy. Operation is NULL.");
return NULL;
}
if(is_inflow)
{
msg = axis2_op_get_msg(op, env, "in");
}
else
{
msg = axis2_op_get_msg(op, env, "out");
}
if(!msg)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rampart_engine] Cannot find policy. Message is NULL.");
return NULL;
}
desc = axis2_msg_get_base(msg, env);
if(!desc)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart][rampart_engine] Cannot find policy. Axis2 description is NULL.");
return NULL;
}
policy_include = axis2_desc_get_policy_include(desc, env);
if(!policy_include)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[rampart][rampart_engine] Policy include is NULL.");
return NULL;
}
service_policy = axis2_policy_include_get_effective_policy(policy_include, env);
if(!service_policy)
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "[rampart][rampart_engine] Policy is NULL.");
return NULL;
}
return service_policy;
}
static axis2_status_t
rampart_engine_set_user_properties(
const axutil_env_t *env,
rampart_context_t *rampart_context)
{
rampart_callback_t* password_callback_module = NULL;
rampart_authn_provider_t *authn_provider = NULL;
rampart_replay_detector_t *replay_detector = NULL;
rampart_sct_provider_t* sct_provider = NULL;
axis2_char_t *pwcb_module_name = NULL;
axis2_char_t *authn_provider_name = NULL;
axis2_char_t *replay_detector_name = NULL;
axis2_char_t *sct_provider_name = NULL;
if(rampart_context_set_user_from_file(rampart_context, env) != AXIS2_SUCCESS)
{
return AXIS2_FAILURE;
}
if(rampart_context_set_ttl_from_file(rampart_context, env) != AXIS2_SUCCESS)
{
return AXIS2_FAILURE;
}
if(rampart_context_set_clock_skew_buffer_from_file(rampart_context, env) != AXIS2_SUCCESS)
{
return AXIS2_FAILURE;
}
if(rampart_context_set_need_millisecond_precision_from_file(rampart_context, env)
!= AXIS2_SUCCESS)
{
return AXIS2_FAILURE;
}
if(rampart_context_set_rd_val_from_file(rampart_context, env) != AXIS2_SUCCESS)
{
return AXIS2_FAILURE;
}
if(rampart_context_set_password_type_from_file(rampart_context, env) != AXIS2_SUCCESS)
{
return AXIS2_FAILURE;
}
pwcb_module_name = rampart_context_get_password_callback_class(rampart_context, env);
if(pwcb_module_name)
{
password_callback_module = rampart_load_pwcb_module(env, pwcb_module_name);
if(password_callback_module)
{
rampart_context_set_password_callback(rampart_context, env, password_callback_module);
}
else
{
return AXIS2_FAILURE;
}
}
authn_provider_name = rampart_context_get_authn_module_name(rampart_context, env);
if(authn_provider_name)
{
authn_provider = rampart_load_auth_module(env, authn_provider_name);
if(authn_provider)
{
rampart_context_set_authn_provider(rampart_context, env, authn_provider);
}
else
{
return AXIS2_FAILURE;
}
}
replay_detector_name = rampart_context_get_replay_detector_name(rampart_context, env);
if(replay_detector_name)
{
replay_detector = rampart_load_replay_detector(env, replay_detector_name);
if(replay_detector)
{
rampart_context_set_replay_detector(rampart_context, env, (void*)replay_detector);
}
else
{
return AXIS2_FAILURE;
}
}
else
{
/* if replay detector is not set, we can use replay detection function. We have to check
* whether user has already set it. If not, we can use default function */
if(!rampart_context_get_replay_detect_function(rampart_context, env))
{
rampart_context_set_replay_detect_function(rampart_context, env,
rampart_replay_detector_default, NULL);
}
}
sct_provider_name = rampart_context_get_sct_provider_name(rampart_context, env);
if(sct_provider_name)
{
sct_provider = rampart_load_sct_provider(env, sct_provider_name);
if(sct_provider)
{
rampart_sct_provider_ops_t *ops = NULL;
rampart_context_set_sct_provider(rampart_context, env, (void*)sct_provider);
ops = sct_provider->ops;
if(ops)
{
void *user_param = NULL;
store_security_context_token_fn store_fn = NULL;
obtain_security_context_token_fn obtain_fn = NULL;
delete_security_context_token_fn delete_fn = NULL;
validate_security_context_token_fn validate_fn = NULL;
/* we have to call sct_provider's get user param method */
if(ops->get_user_params)
{
user_param = ops->get_user_params(env);
rampart_context_set_security_context_token_user_params(rampart_context, env,
user_param);
}
else
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart]Cannot find 'get user param' operation of secrutiy context token "
"provider.");
return AXIS2_FAILURE;
}
/* get function pointers and set it to rampart context */
store_fn = ops->store_security_context_token;
if(store_fn)
{
rampart_context_set_store_security_context_token_fn(rampart_context, env,
store_fn);
}
else
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart]Cannot find 'store' operation of secrutiy context token provider.");
return AXIS2_FAILURE;
}
obtain_fn = ops->obtain_security_context_token;
if(obtain_fn)
{
rampart_context_set_obtain_security_context_token_fn(rampart_context, env,
obtain_fn);
}
else
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart]Cannot find 'obtain' operation of secrutiy context token provider.");
return AXIS2_FAILURE;
}
delete_fn = ops->delete_security_context_token;
if(delete_fn)
{
rampart_context_set_delete_security_context_token_fn(rampart_context, env,
delete_fn);
}
else
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart]Cannot find 'delete' operation of secrutiy context token provider.");
return AXIS2_FAILURE;
}
validate_fn = ops->validate_security_context_token;
if(validate_fn)
{
rampart_context_set_validate_security_context_token_fn(rampart_context, env,
validate_fn);
}
else
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart]Cannot find 'validate' operation of secrutiy context token provider.");
return AXIS2_FAILURE;
}
}
else
{
AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI,
"[rampart]Cannot find operations of secrutiy context token provider.");
return AXIS2_FAILURE;
}
}
else
{
return AXIS2_FAILURE;
}
}
else
{
/* If sct_provider is not set, we can use sct functions. We have to check whether user has
* already set it. If not, we can use default function */
if(!rampart_context_get_obtain_security_context_token_fn(rampart_context, env))
{
rampart_context_set_obtain_security_context_token_fn(rampart_context, env,
sct_provider_obtain_sct_default);
}
if(!rampart_context_get_store_security_context_token_fn(rampart_context, env))
{
rampart_context_set_store_security_context_token_fn(rampart_context, env,
sct_provider_store_sct_default);
}
if(!rampart_context_get_delete_security_context_token_fn(rampart_context, env))
{
rampart_context_set_delete_security_context_token_fn(rampart_context, env,
sct_provider_delete_sct_default);
}
if(!rampart_context_get_validate_security_context_token_fn(rampart_context, env))
{
rampart_context_set_validate_security_context_token_fn(rampart_context, env,
sct_provider_validate_sct_default);
}
}
return AXIS2_SUCCESS;
}
static axis2_status_t
rampart_engine_retrieve_key_mgr_prop_from_policy(
rampart_context_t *rampart_context,
const axutil_env_t *env)
{
axis2_char_t *value = NULL;
rp_rampart_config_t *config = NULL;
oxs_key_mgr_t *key_mgr = NULL;
rp_secpolicy_t *secpolicy = NULL;
secpolicy = rampart_context_get_secpolicy(rampart_context, env);
config = rp_secpolicy_get_rampart_config(secpolicy, env);
if(!config)
return AXIS2_FAILURE;
key_mgr = rampart_context_get_key_mgr(rampart_context, env);
value = rp_rampart_config_get_certificate_file(config, env);
if(value)
{
oxs_key_mgr_set_certificate_file(key_mgr, env, value);
}
value = rp_rampart_config_get_private_key_file(config, env);
if(value)
{
oxs_key_mgr_set_private_key_file(key_mgr, env, value);
}
value = rp_rampart_config_get_receiver_certificate_file(config, env);
if(value)
{
oxs_key_mgr_set_reciever_certificate_file(key_mgr, env, value);
}
return AXIS2_SUCCESS;
}