blob: 344c59316904baf755e2e482f751e48c7eb9a1b7 [file] [log] [blame]
/*
*Copyright 2004,2005 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_qname.h>
#include <axis2_svc.h>
#include <axiom_soap_header.h>
#include <axiom_soap_body.h>
#include <axiom_soap_header_block.h>
#include <axis2_endpoint_ref.h>
#include <axis2_property.h>
#include <rampart_constants.h>
#include <rampart_crypto_util.h>
#include <rampart_util.h>
#include <rampart_timestamp_token.h>
#include <oxs_axiom.h>
typedef struct rampart_timestamp_token_impl
{
rampart_timestamp_token_t timestamp_token;
}
rampart_timestamp_token_impl_t;
/** Interface to implementation conversion macro */
#define AXIS2_INTF_TO_IMPL(timestamp_token) ((rampart_timestamp_token_impl_t *)timestamp_token)
/*************************** Function headers *********************************/
/** private functions */
static void
rampart_timestamp_token_init_ops(
rampart_timestamp_token_t *timestamp_token);
/** public functions*/
axis2_status_t AXIS2_CALL
rampart_timestamp_token_free(rampart_timestamp_token_t *timestamp_token,
const axis2_env_t *env);
axis2_status_t AXIS2_CALL
rampart_timestamp_token_build(rampart_timestamp_token_t *timestamp_token,
const axis2_env_t *env,
const axis2_ctx_t *ctx,
axiom_node_t *sec_node,
const axiom_namespace_t *sec_ns_obj,
int ttl);
axis2_status_t AXIS2_CALL
rampart_timestamp_token_validate(rampart_timestamp_token_t *timestamp_token,
const axis2_env_t *env,
axiom_node_t *ts_node,
axis2_array_list_t *sub_codes);
/*************************** end of function headers *********************************/
static void
rampart_timestamp_token_init_ops(
rampart_timestamp_token_t *timestamp_token)
{
timestamp_token->ops->free = rampart_timestamp_token_free;
timestamp_token->ops->build = rampart_timestamp_token_build;
timestamp_token->ops->validate = rampart_timestamp_token_validate;
}
rampart_timestamp_token_t *AXIS2_CALL
rampart_timestamp_token_create(
const axis2_env_t *env)
{
rampart_timestamp_token_impl_t *timestamp_token_impl = NULL;
AXIS2_ENV_CHECK(env, NULL);
timestamp_token_impl = (rampart_timestamp_token_impl_t *) AXIS2_MALLOC(env->allocator,
sizeof(rampart_timestamp_token_impl_t));
if (NULL == timestamp_token_impl)
{
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
return NULL;
}
timestamp_token_impl->timestamp_token.ops = AXIS2_MALLOC(env->allocator,
sizeof(rampart_timestamp_token_ops_t));
if (NULL == timestamp_token_impl->timestamp_token.ops)
{
rampart_timestamp_token_free(&(timestamp_token_impl->timestamp_token), env);
AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE);
return NULL;
}
rampart_timestamp_token_init_ops(&(timestamp_token_impl->timestamp_token));
return &(timestamp_token_impl->timestamp_token);
}
axis2_status_t AXIS2_CALL
rampart_timestamp_token_free(rampart_timestamp_token_t *timestamp_token,
const axis2_env_t *env)
{
rampart_timestamp_token_impl_t *timestamp_token_impl = NULL;
AXIS2_ENV_CHECK(env, AXIS2_FAILURE);
timestamp_token_impl = AXIS2_INTF_TO_IMPL(timestamp_token);
if (timestamp_token->ops)
{
AXIS2_FREE(env->allocator, timestamp_token->ops);
timestamp_token->ops = NULL;
}
if (timestamp_token_impl)
{
AXIS2_FREE(env->allocator, timestamp_token_impl);
timestamp_token_impl = NULL;
}
return AXIS2_SUCCESS;
}
axis2_status_t AXIS2_CALL
rampart_timestamp_token_build(rampart_timestamp_token_t *timestamp_token,
const axis2_env_t *env,
const axis2_ctx_t *ctx,
axiom_node_t *sec_node,
const axiom_namespace_t *sec_ns_obj,
int ttl)
{
axiom_node_t *ts_node = NULL;
axiom_node_t *created_node = NULL;
axiom_node_t *expires_node = NULL;
axiom_element_t *ts_ele = NULL;
axiom_element_t *created_ele = NULL;
axiom_element_t *expires_ele = NULL;
axis2_char_t *created_val = NULL;
axis2_char_t *expires_val = NULL;
axiom_namespace_t *wsu_ns_obj = NULL;
wsu_ns_obj = axiom_namespace_create(env, RAMPART_WSU_XMLNS,
RAMPART_WSU);
ts_ele = axiom_element_create(env, sec_node,
RAMPART_SECURITY_TIMESTAMP,
wsu_ns_obj,
&ts_node);
if (ts_ele)
{
/*First we build Created element*/
created_ele = axiom_element_create(env, ts_node, RAMPART_SECURITY_TIMESTAMP_CREATED, wsu_ns_obj,
&created_node);
if (created_ele)
{
created_val = rampart_generate_time(env, 0); /*Current time*/
AXIOM_ELEMENT_SET_TEXT(created_ele, env, created_val, created_node);
}
/*Then we build Expires element*/
expires_ele = axiom_element_create(env, ts_node, RAMPART_SECURITY_TIMESTAMP_EXPIRES, wsu_ns_obj,
&expires_node);
if (expires_ele)
{
expires_val = rampart_generate_time(env, ttl);
AXIOM_ELEMENT_SET_TEXT(expires_ele, env, expires_val, expires_node);
}
}
return AXIS2_SUCCESS;
}/*rampart_build_timestamp_token*/
axis2_status_t AXIS2_CALL
rampart_timestamp_token_validate(rampart_timestamp_token_t *timestamp_token,
const axis2_env_t *env,
axiom_node_t *ts_node,
axis2_array_list_t *sub_codes)
{
axis2_status_t validity = AXIS2_FAILURE;
axiom_element_t *created_ele = NULL;
axiom_element_t *expires_ele = NULL;
axiom_element_t *ts_ele = NULL;
axiom_node_t *created_node = NULL;
axiom_node_t *expires_node = NULL;
axis2_char_t *created_val = NULL;
axis2_char_t *expires_val = NULL;
axis2_char_t *current_val = NULL;
/*Check: TIMESTAMP MUST contain exactly one CREATED*/
if (1 != oxs_axiom_get_number_of_children_with_qname(env, ts_node, RAMPART_SECURITY_TIMESTAMP_CREATED, NULL, NULL))
{
AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Timestamp must contain exactly one Created element");
return AXIS2_FAILURE;
}
/*Check: TIMESTAMP MUST NOT contain more than one EXPIRES*/
if (1 < oxs_axiom_get_number_of_children_with_qname(env, ts_node, RAMPART_SECURITY_TIMESTAMP_CREATED, NULL, NULL))
{
AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Timestamp must not contain more than one Expires element");
return AXIS2_FAILURE;
}
ts_ele = AXIOM_NODE_GET_DATA_ELEMENT(ts_node, env);
if (!ts_ele)
{
AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Cannot find Timestamp element");
AXIS2_LOG_INFO(env->log, " Cannot find timestamp ... ");
return AXIS2_FAILURE;
}
/*First child MUST be the Created element*/
created_node = AXIOM_NODE_GET_FIRST_CHILD(ts_node, env);
created_ele = (axiom_element_t*)AXIOM_NODE_GET_DATA_ELEMENT(created_node, env);
if (AXIS2_STRCMP(RAMPART_SECURITY_TIMESTAMP_CREATED ,
AXIOM_ELEMENT_GET_LOCALNAME(created_ele, env)) != 0)
{
AXIS2_ARRAY_LIST_ADD(sub_codes, env, "The first elelment of a Timestamp token must be Created");
AXIS2_LOG_INFO(env->log, "Cannot find created in timestamp element. The first element MUST be CREATED");
return AXIS2_FAILURE;
}
created_val = AXIOM_ELEMENT_GET_TEXT(created_ele, env, created_node);
/*Check weather created is less than current time or not*/
current_val = rampart_generate_time(env, 0);
validity = rampart_compare_date_time(env, created_val, current_val);
if (validity == AXIS2_FAILURE)
{
AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Created time is not valid");
return AXIS2_FAILURE;
}
/*Any TIMESTAMP containing an EXPIRES MUST contain a CREATED that preceeds its sibling EXPIRES.*/
expires_node = AXIOM_NODE_GET_NEXT_SIBLING(created_node, env);
if (!expires_node)
{
AXIS2_LOG_INFO(env->log, "Cannot find expires in timestamp element...");
/*If the expire element is not present, it means that the message will not be expired.*/
return AXIS2_SUCCESS;
}
expires_ele = (axiom_element_t*)AXIOM_NODE_GET_DATA_ELEMENT(expires_node, env);
if (AXIS2_STRCMP(RAMPART_SECURITY_TIMESTAMP_EXPIRES ,
AXIOM_ELEMENT_GET_LOCALNAME(expires_ele, env)) != 0)
{
AXIS2_LOG_INFO(env->log, " The second element of timestamp token (if any) MUST be EXPIRES");
AXIS2_ARRAY_LIST_ADD(sub_codes, env, "The second elelment must be Expires, if any");
return AXIS2_FAILURE;
}
/*Now the expires element is present. So check weather this has a valid timestamp.
If not it's a failure*/
expires_val = AXIOM_ELEMENT_GET_TEXT(expires_ele, env, expires_node);
/*Check weather time has expired or not*/
validity = rampart_compare_date_time(env, current_val, expires_val);
if (validity == AXIS2_FAILURE)
{
AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Timestamp token has expired");
return AXIS2_FAILURE;
}
/*free memory for qnames*/
return validity;
}