| /* |
| *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_username_token.h> |
| #include <rampart_constants.h> |
| #include <rampart_crypto_util.h> |
| #include <rampart_util.h> |
| #include <rampart_callback.h> |
| #include <rampart_handler_util.h> |
| #include <oxs_axiom.h> |
| |
| typedef struct rampart_username_token_impl |
| { |
| rampart_username_token_t username_token; |
| } |
| rampart_username_token_impl_t; |
| |
| /** Interface to implementation conversion macro */ |
| #define AXIS2_INTF_TO_IMPL(username_token) ((rampart_username_token_impl_t *)username_token) |
| |
| /*************************** Function headers *********************************/ |
| /** private functions */ |
| static void |
| rampart_username_token_init_ops( |
| rampart_username_token_t *username_token); |
| /** |
| * Get the password for given outflow security configuration |
| * @param env pointer to environment struct |
| * @param ctx axis2 context |
| * @param Outflow security parameter |
| * @return password |
| */ |
| static axis2_char_t* |
| rampart_get_password(const axis2_env_t *env, |
| axis2_ctx_t *ctx, |
| rampart_actions_t *actions); |
| /** |
| * |
| * @param env pointer to environment struct |
| * @param ctx axis2 context |
| * @return property value |
| */ |
| static axis2_char_t* |
| rampart_username_token_callback_pw(const axis2_env_t *env, |
| axis2_char_t *callback_module_name, |
| const axis2_char_t *username); |
| |
| /** public functions*/ |
| axis2_status_t AXIS2_CALL |
| rampart_username_token_free(rampart_username_token_t *username_token, |
| const axis2_env_t *env); |
| |
| axis2_status_t AXIS2_CALL |
| rampart_username_token_build(rampart_username_token_t *username_token, |
| const axis2_env_t *env, |
| axis2_ctx_t *ctx, |
| rampart_actions_t *actions, |
| axiom_node_t *sec_node, |
| axiom_namespace_t *sec_ns_obj); |
| |
| |
| axis2_status_t AXIS2_CALL |
| rampart_username_token_validate(rampart_username_token_t *username_token, |
| const axis2_env_t *env, |
| axis2_msg_ctx_t *msg_ctx, |
| axiom_soap_header_t *soap_header, |
| rampart_actions_t *actions, |
| axis2_array_list_t *sub_codes); |
| |
| /************************* End of function headers ****************************/ |
| static void |
| rampart_username_token_init_ops( |
| rampart_username_token_t *username_token) |
| { |
| username_token->ops->free = rampart_username_token_free; |
| username_token->ops->build = rampart_username_token_build; |
| username_token->ops->validate = rampart_username_token_validate; |
| } |
| |
| |
| static axis2_char_t * |
| rampart_get_password(const axis2_env_t *env, |
| axis2_ctx_t *ctx, |
| rampart_actions_t *actions) |
| { |
| axis2_char_t *password = NULL; |
| axis2_char_t *username = NULL; |
| axis2_char_t *pw_callback_module = NULL; |
| |
| /*Check if password is in the context. |
| i.e.In any context in the cotext hierarchy starting from msg, op, svc, etc.*/ |
| password = rampart_get_property_from_ctx(env, ctx, RAMPART_ACTION_PASSWORD); |
| if (password) |
| { |
| return password; |
| } |
| |
| /*If not check weather there is a callback class specified*/ |
| pw_callback_module = RAMPART_ACTIONS_GET_PW_CB_CLASS(actions, env); |
| if (pw_callback_module) |
| { |
| username = RAMPART_ACTIONS_GET_USER(actions, env); |
| password = rampart_username_token_callback_pw(env, pw_callback_module, username); |
| } |
| return password; |
| } |
| |
| |
| static axis2_char_t* |
| rampart_username_token_callback_pw(const axis2_env_t *env, |
| axis2_char_t *callback_module_name, |
| const axis2_char_t *username) |
| { |
| rampart_callback_t* rcb = NULL; |
| axis2_char_t *password = NULL; |
| axis2_dll_desc_t *dll_desc = NULL; |
| void *ptr = NULL; |
| axis2_param_t *impl_info_param = NULL; |
| |
| dll_desc = axis2_dll_desc_create(env); |
| AXIS2_DLL_DESC_SET_NAME(dll_desc, env, callback_module_name); |
| impl_info_param = axis2_param_create(env, NULL, NULL); |
| AXIS2_PARAM_SET_VALUE(impl_info_param, env, dll_desc); |
| axis2_class_loader_init(env); |
| ptr = axis2_class_loader_create_dll(env, impl_info_param); |
| |
| /*callback()*/ |
| if (!ptr) |
| { |
| printf("\nCallback ptr is null"); |
| return NULL; |
| } |
| |
| rcb = (rampart_callback_t*)ptr; |
| if (!rcb) |
| { |
| printf("\nrampart_callback_t is null"); |
| return NULL; |
| } |
| /*Get the password thru the callback*/ |
| password = RAMPART_CALLBACK_CALLBACK_PASSWORD(rcb, env, username); |
| |
| return password; |
| } |
| |
| rampart_username_token_t *AXIS2_CALL |
| rampart_username_token_create( |
| const axis2_env_t *env) |
| { |
| rampart_username_token_impl_t *username_token_impl = NULL; |
| |
| AXIS2_ENV_CHECK(env, NULL); |
| |
| username_token_impl = (rampart_username_token_impl_t *) AXIS2_MALLOC(env->allocator, |
| sizeof(rampart_username_token_impl_t)); |
| |
| if (NULL == username_token_impl) |
| { |
| AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| return NULL; |
| } |
| |
| username_token_impl->username_token.ops = AXIS2_MALLOC(env->allocator, |
| sizeof(rampart_username_token_ops_t)); |
| if (NULL == username_token_impl->username_token.ops) |
| { |
| rampart_username_token_free(&(username_token_impl->username_token), env); |
| AXIS2_ERROR_SET(env->error, AXIS2_ERROR_NO_MEMORY, AXIS2_FAILURE); |
| return NULL; |
| } |
| |
| rampart_username_token_init_ops(&(username_token_impl->username_token)); |
| |
| return &(username_token_impl->username_token); |
| |
| } |
| |
| axis2_status_t AXIS2_CALL |
| rampart_username_token_free(rampart_username_token_t *username_token, |
| const axis2_env_t *env) |
| { |
| rampart_username_token_impl_t *username_token_impl = NULL; |
| |
| AXIS2_ENV_CHECK(env, AXIS2_FAILURE); |
| username_token_impl = AXIS2_INTF_TO_IMPL(username_token); |
| |
| if (username_token->ops) |
| { |
| AXIS2_FREE(env->allocator, username_token->ops); |
| username_token->ops = NULL; |
| } |
| if (username_token_impl) |
| { |
| AXIS2_FREE(env->allocator, username_token_impl); |
| username_token_impl = NULL; |
| } |
| return AXIS2_SUCCESS; |
| |
| } |
| |
| axis2_status_t AXIS2_CALL |
| rampart_username_token_build(rampart_username_token_t *username_token, |
| const axis2_env_t *env, |
| axis2_ctx_t *ctx, |
| rampart_actions_t *actions, |
| axiom_node_t *sec_node, |
| axiom_namespace_t *sec_ns_obj |
| ) |
| { |
| |
| axiom_node_t *ut_node = NULL; |
| axiom_node_t *un_node = NULL; |
| axiom_node_t *pw_node = NULL; |
| axiom_node_t *nonce_node = NULL; |
| axiom_node_t *created_node = NULL; |
| axiom_element_t *ut_ele = NULL; |
| axiom_element_t *un_ele = NULL; |
| axiom_element_t *pw_ele = NULL; |
| axiom_element_t *nonce_ele = NULL; |
| axiom_element_t *created_ele = NULL; |
| axis2_char_t *username = NULL; |
| axis2_char_t *password = NULL; |
| axis2_char_t *password_type = NULL; |
| axiom_namespace_t *wsu_ns_obj = NULL; |
| axiom_attribute_t *om_attr = NULL; |
| rampart_username_token_impl_t *username_token_impl = NULL; |
| |
| AXIS2_ENV_CHECK(env, AXIS2_FAILURE); |
| username_token_impl = AXIS2_INTF_TO_IMPL(username_token); |
| |
| /*Get values from outflow security*/ |
| |
| username = RAMPART_ACTIONS_GET_USER(actions, env); |
| password_type = RAMPART_ACTIONS_GET_PASSWORD_TYPE(actions, env); |
| |
| password = rampart_get_password(env, ctx, actions); |
| |
| if (!password) |
| { |
| return AXIS2_FAILURE; |
| } |
| |
| ut_ele = axiom_element_create(env, sec_node, |
| RAMPART_SECURITY_USERNAMETOKEN, |
| sec_ns_obj, |
| &ut_node); |
| |
| wsu_ns_obj = axiom_namespace_create(env, RAMPART_WSU_XMLNS, |
| RAMPART_WSU); |
| AXIOM_ELEMENT_DECLARE_NAMESPACE(ut_ele, env, |
| ut_node, wsu_ns_obj); |
| |
| if (ut_ele) |
| { |
| |
| un_ele = axiom_element_create(env, ut_node, RAMPART_SECURITY_USERNAMETOKEN_USERNAME, sec_ns_obj, |
| &un_node); |
| if (un_ele) |
| { |
| axiom_namespace_t *dec_ns = NULL; |
| AXIOM_ELEMENT_SET_TEXT(un_ele, env, username, un_node); |
| dec_ns = AXIOM_ELEMENT_FIND_DECLARED_NAMESPACE(un_ele, env, |
| RAMPART_WSSE_XMLNS, |
| RAMPART_WSSE); |
| |
| |
| AXIOM_ELEMENT_SET_NAMESPACE(un_ele, env, sec_ns_obj, un_node); |
| |
| } |
| |
| if (0 == AXIS2_STRCMP(password_type, RAMPART_PASSWORD_DIGEST)) |
| { |
| axis2_char_t *nonce_val = NULL; |
| axis2_char_t *created_val = NULL; |
| axis2_char_t *digest_val = NULL; |
| axiom_namespace_t *dec_ns = NULL; |
| |
| nonce_val = rampart_generate_nonce(env) ; |
| created_val = rampart_generate_time(env, 0); |
| digest_val = rampart_crypto_sha1(env, nonce_val, created_val, password); |
| |
| pw_ele = axiom_element_create(env, ut_node, RAMPART_SECURITY_USERNAMETOKEN_PASSWORD, sec_ns_obj, |
| &pw_node); |
| if (pw_ele) |
| { |
| |
| AXIOM_ELEMENT_SET_TEXT(pw_ele, env, digest_val, pw_node); |
| dec_ns = AXIOM_ELEMENT_FIND_DECLARED_NAMESPACE(pw_ele, env, |
| RAMPART_WSSE_XMLNS, |
| RAMPART_WSSE); |
| |
| |
| om_attr = axiom_attribute_create(env, |
| RAMPART_SECURITY_USERNAMETOKEN_PASSWORD_ATTR_TYPE, |
| RAMPART_PASSWORD_DIGEST_URI, |
| NULL); |
| |
| AXIOM_ELEMENT_ADD_ATTRIBUTE(pw_ele, env, |
| om_attr, pw_node); |
| |
| } |
| nonce_ele = axiom_element_create(env, ut_node, RAMPART_SECURITY_USERNAMETOKEN_NONCE, sec_ns_obj, |
| &nonce_node); |
| if (nonce_ele) |
| { |
| axiom_namespace_t *dec_ns = NULL; |
| AXIOM_ELEMENT_SET_TEXT(nonce_ele, env, nonce_val , nonce_node); |
| dec_ns = AXIOM_ELEMENT_FIND_DECLARED_NAMESPACE(nonce_ele, env, |
| RAMPART_WSSE_XMLNS, |
| RAMPART_WSSE); |
| } |
| created_ele = axiom_element_create(env, ut_node, RAMPART_SECURITY_USERNAMETOKEN_CREATED, sec_ns_obj, |
| &created_node); |
| if (created_ele) |
| { |
| axiom_namespace_t *dec_ns = NULL; |
| AXIOM_ELEMENT_SET_TEXT(created_ele, env, created_val, created_node); |
| dec_ns = AXIOM_ELEMENT_FIND_DECLARED_NAMESPACE(created_ele, env, |
| RAMPART_WSSE_XMLNS, |
| RAMPART_WSSE); |
| |
| AXIOM_ELEMENT_SET_NAMESPACE(created_ele, env, wsu_ns_obj, created_node); |
| |
| } |
| |
| if(nonce_val){ |
| AXIS2_FREE(env->allocator, nonce_val); |
| nonce_val = NULL; |
| } |
| if(created_val){ |
| AXIS2_FREE(env->allocator, created_val); |
| created_val = NULL; |
| } |
| if(digest_val){ |
| AXIS2_FREE(env->allocator, digest_val); |
| digest_val = NULL; |
| } |
| } |
| else /*default is passwordText*/ |
| { |
| pw_ele = axiom_element_create(env, ut_node, RAMPART_SECURITY_USERNAMETOKEN_PASSWORD, sec_ns_obj, |
| &pw_node); |
| if (pw_ele) |
| { |
| axiom_namespace_t *dec_ns = NULL; |
| AXIOM_ELEMENT_SET_TEXT(pw_ele, env, password, pw_node); |
| dec_ns = AXIOM_ELEMENT_FIND_DECLARED_NAMESPACE(pw_ele, env, |
| RAMPART_WSSE_XMLNS, |
| RAMPART_WSSE); |
| |
| om_attr = axiom_attribute_create(env, |
| RAMPART_SECURITY_USERNAMETOKEN_PASSWORD_ATTR_TYPE, |
| RAMPART_PASSWORD_TEXT_URI, |
| NULL); |
| |
| AXIOM_ELEMENT_ADD_ATTRIBUTE(pw_ele, env, |
| om_attr, pw_node); |
| } |
| } /*End if passwordType == passwordText*/ |
| } |
| return AXIS2_SUCCESS; |
| } |
| |
| axis2_status_t AXIS2_CALL |
| rampart_username_token_validate(rampart_username_token_t *username_token, |
| const axis2_env_t *env, |
| axis2_msg_ctx_t *msg_ctx, |
| axiom_soap_header_t *soap_header, |
| rampart_actions_t *actions, |
| axis2_array_list_t *sub_codes) |
| { |
| axiom_element_t *sec_ele = NULL; |
| axiom_element_t *ut_ele = NULL; |
| axiom_node_t *sec_node = NULL; |
| axiom_node_t *ut_node = NULL; |
| axiom_child_element_iterator_t *children = NULL; |
| axis2_char_t *username = NULL; |
| axis2_char_t *password = NULL; |
| axis2_char_t *nonce = NULL; |
| axis2_char_t *created = NULL; |
| axis2_char_t *password_type = NULL; |
| axis2_char_t *pw_callback_module = NULL; |
| axis2_char_t *password_from_svr = NULL; |
| axis2_char_t *password_to_compare = NULL; |
| axis2_ctx_t *ctx = NULL; |
| axis2_qname_t *qname = NULL; |
| rampart_username_token_impl_t *username_token_impl = NULL; |
| |
| AXIS2_ENV_CHECK(env, AXIS2_FAILURE); |
| username_token_impl = AXIS2_INTF_TO_IMPL(username_token); |
| |
| sec_node = rampart_get_security_token(env, msg_ctx, soap_header); |
| if (!sec_node) |
| { |
| AXIS2_LOG_INFO(env->log, " Cannot find sec_node.. :("); |
| return AXIS2_FAILURE; |
| } |
| |
| |
| sec_ele = AXIOM_NODE_GET_DATA_ELEMENT(sec_node, env); |
| if (!sec_ele) |
| { |
| AXIS2_LOG_INFO(env->log, " Cannot find sec_ele... :("); |
| return AXIS2_FAILURE; |
| } |
| |
| qname = axis2_qname_create(env, |
| RAMPART_SECURITY_USERNAMETOKEN, |
| RAMPART_WSSE_XMLNS, |
| RAMPART_WSSE); |
| if (qname) |
| { |
| ut_ele = AXIOM_ELEMENT_GET_FIRST_CHILD_WITH_QNAME(sec_ele, env, qname, sec_node, &ut_node); |
| if (!ut_ele) |
| { |
| AXIS2_LOG_INFO(env->log, "Cannot find UsernameToken in Security element..."); |
| AXIS2_ARRAY_LIST_ADD(sub_codes, env, "No username token in the security header"); |
| return AXIS2_FAILURE; |
| } |
| } |
| |
| /*Check: Any USERNAME_TOKEN MUST NOT have more than one PASSWORD*/ |
| if (1 < oxs_axiom_get_number_of_children_with_qname(env, ut_node, RAMPART_SECURITY_USERNAMETOKEN_PASSWORD, NULL, NULL)) |
| { |
| AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Username token must not have more than one password"); |
| return AXIS2_FAILURE; |
| } |
| |
| /*Check: Any USERNAME_TOKEN MUST NOT have more than one CREATED*/ |
| if (1 < oxs_axiom_get_number_of_children_with_qname(env, ut_node, RAMPART_SECURITY_USERNAMETOKEN_CREATED, NULL, NULL)) |
| { |
| AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Username token must not have more than one creted element"); |
| return AXIS2_FAILURE; |
| } |
| |
| /*Check: Any USERNAME_TOKEN MUST NOT have more than one NONCE*/ |
| if (1 < oxs_axiom_get_number_of_children_with_qname(env, ut_node, RAMPART_SECURITY_USERNAMETOKEN_NONCE, NULL, NULL)) |
| { |
| AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Username token must not have more than one nonce element"); |
| return AXIS2_FAILURE; |
| } |
| |
| /*Get children of UsernameToken element*/ |
| children = AXIOM_ELEMENT_GET_CHILD_ELEMENTS(ut_ele, env, ut_node); |
| if (children) |
| { |
| /*Go thru children and find username token parameters*/ |
| while (AXIS2_TRUE == AXIOM_CHILD_ELEMENT_ITERATOR_HAS_NEXT(children, env)) |
| { |
| axiom_node_t *node = NULL; |
| axiom_element_t *element = NULL; |
| axis2_char_t *localname = NULL; |
| |
| node = AXIOM_CHILD_ELEMENT_ITERATOR_NEXT(children, env); |
| element = AXIOM_NODE_GET_DATA_ELEMENT(node, env); |
| localname = AXIOM_ELEMENT_GET_LOCALNAME(element, env); |
| |
| if (0 == AXIS2_STRCMP(localname, RAMPART_SECURITY_USERNAMETOKEN_USERNAME)) |
| { |
| username = AXIOM_ELEMENT_GET_TEXT(element, env, node); |
| |
| } |
| else if (0 == AXIS2_STRCMP(localname , RAMPART_SECURITY_USERNAMETOKEN_PASSWORD)) |
| { |
| password_type = AXIOM_ELEMENT_GET_ATTRIBUTE_VALUE_BY_NAME(element, |
| env, |
| RAMPART_SECURITY_USERNAMETOKEN_PASSWORD_ATTR_TYPE); |
| |
| if (!password_type) |
| { |
| /*R4201 Any PASSWORD MUST specify a Type attribute */ |
| AXIS2_LOG_INFO(env->log, "Password Type is not specified in the password element"); |
| AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Password Type is not specified in the password element"); |
| return AXIS2_FAILURE; |
| } |
| |
| password = AXIOM_ELEMENT_GET_TEXT(element, env, node); |
| |
| } |
| else if (0 == AXIS2_STRCMP(localname, RAMPART_SECURITY_USERNAMETOKEN_NONCE)) |
| { |
| nonce = AXIOM_ELEMENT_GET_TEXT(element, env, node); |
| |
| } |
| else if (0 == AXIS2_STRCMP(localname , RAMPART_SECURITY_USERNAMETOKEN_CREATED)) |
| { |
| created = AXIOM_ELEMENT_GET_TEXT(element, env, node); |
| |
| } |
| else |
| { |
| AXIS2_LOG_INFO(env->log, "\nUnknown element found %s -> %s", localname, AXIOM_ELEMENT_GET_TEXT(element, env, node)); |
| } |
| |
| |
| }/*end of while*/ |
| } |
| else |
| { |
| AXIS2_LOG_INFO(env->log, "Cannot find child elements of Usernametoken"); |
| return AXIS2_FAILURE; |
| } |
| |
| /*Now we process collected usernametoken parameters*/ |
| if (!username) |
| { |
| return AXIS2_FAILURE; |
| } |
| |
| ctx = AXIS2_MSG_CTX_GET_BASE(msg_ctx, env); |
| pw_callback_module = RAMPART_ACTIONS_GET_PW_CB_CLASS(actions, env); |
| |
| password_from_svr = rampart_username_token_callback_pw(env, pw_callback_module, username); |
| |
| if (!password_from_svr) |
| { |
| return AXIS2_FAILURE; |
| } |
| /*Alright NOW we have the password. Is digest needed?*/ |
| if (0 == AXIS2_STRCMP(password_type, RAMPART_PASSWORD_DIGEST_URI)) |
| { |
| password_to_compare = rampart_crypto_sha1(env, nonce, created, password_from_svr); |
| } |
| else |
| { |
| password_to_compare = password_from_svr; |
| } |
| |
| /*The BIG moment. Compare passwords*/ |
| if (0 == AXIS2_STRCMP(password_to_compare , password)) |
| { |
| AXIS2_ARRAY_LIST_ADD(sub_codes, env, "Password is not valid"); |
| return AXIS2_SUCCESS; |
| } |
| else |
| { |
| return AXIS2_FAILURE; |
| } |
| } |