static int vxlan_fdb_append(struct vxlan_fdb *f, __be32 ip, __be16 port, uint32_t vni, uint32_t ifindex,struct vxlan_dev *vdev,uint32_t index) { struct vxlan_rdst *rd_prev, *rd; rd_prev = NULL; for (rd = &f->remote; rd; rd = rd->remote_next) { if (rd->remote_ip == ip && rd->remote_port == port && rd->remote_vni == vni && rd->remote_ifindex == ifindex) return 0; rd_prev = rd; } rd = pal_malloc(sizeof(*rd)); if (rd == NULL) return -ENOMEM; rd->remote_ip = ip; rd->remote_port = port; rd->remote_vni = vni; rd->remote_ifindex = ifindex; rd->remote_next = NULL; write_lock_vxlan_fdb(vdev,index); rd_prev->remote_next = rd; write_unlock_vxlan_fdb(vdev,index); return 1; }
// -------------------------------------------------------------------------- // // void ExtractChallenge(tChallenge *c, char *String) { char *s, *e, *Token, *Value; int len; memset(c, 0, sizeof(tChallenge)); Token = (char*) pal_malloc( pal_strlen(String)+1 ); Value = (char*) pal_malloc( pal_strlen(String)+1 ); *Token=*Value=0; for(s=e=String; ; e++) { if(*e== ',' || *e == '\r' || *e == '\n' || *e==0) { if(s!=e) { if(*Token && (*Value==0)) { len = (int)((char *)e-(char *)s); /* Chop the quotes */ if((*s == '"') && len) { s++; len--; } if((s[len-1] == '"') && len) len--; if(len) memcpy(Value, s, len); Value[len] = 0; } if(*Token && *Value) { InsertInChallegeStruct(c, Token,Value); *Value = *Token = 0; } } if(*e == 0) break; s = ++e; } if((*e=='=' || *e== ',' || *e == '\r' || *e == '\n' || *e==0) && (*Token == 0) && (e != s)) { len = (int)((char *)e-(char *)s); memcpy(Token, s, len); Token[len] = 0; if(*e == 0) break; s = ++e; } } pal_free( Token ); pal_free( Value ); }
PAL_RET_E pal_sem_create( PAL_SEM_HDL *phl_sem_hdl, PAL_SEM_CREATE_PARAM_X *px_create_param) { PAL_RET_E e_error = ePAL_RET_FAILURE; PAL_SEM_CTXT_X *px_sem_ctxt = NULL; int i_sem_ret_val = -1; if ((NULL == phl_sem_hdl) || (NULL == px_create_param)) { PAL_LOG_HIGH("Invalid Args"); e_error = ePAL_RET_INVALID_ARGS; goto LBL_CLEANUP; } if (px_create_param->ui_max_count > PAL_SEM_VALUE_MAX) { PAL_LOG_HIGH("Invalid Args. ui_max_count cannot be greater than %d" " (PAL_SEM_VALUE_MAX)", PAL_SEM_VALUE_MAX); e_error = ePAL_RET_INVALID_ARGS; goto LBL_CLEANUP; } *phl_sem_hdl = NULL; px_sem_ctxt = (PAL_SEM_CTXT_X *) pal_malloc (sizeof(PAL_SEM_CTXT_X), NULL); if(NULL == px_sem_ctxt) { PAL_LOG_HIGH("pal_malloc failed: %p", px_sem_ctxt); e_error = ePAL_RET_OUT_OF_MEMORY; goto LBL_CLEANUP; } (void) pal_memmove (&(px_sem_ctxt->x_create_param), px_create_param, sizeof(px_sem_ctxt->x_create_param)); px_sem_ctxt->hl_sem_hdl = CreateSemaphore(NULL, px_create_param->ui_initial_count, px_create_param->ui_max_count, NULL); if (NULL == px_sem_ctxt->hl_sem_hdl) { perror ("sem_init"); PAL_LOG_HIGH("CreateSemaphore failed: %d, Errno: %d", i_sem_ret_val, errno); pal_free (px_sem_ctxt); px_sem_ctxt = NULL; e_error = ePAL_RET_SEM_CREATE_FAILED; } else { PAL_LOG_FULL("CreateSemaphore success. Initial: %d, Max: %d", px_create_param->ui_initial_count, px_create_param->ui_max_count); *phl_sem_hdl = (PAL_SEM_HDL) px_sem_ctxt; e_error = ePAL_RET_SUCCESS; } LBL_CLEANUP: return e_error; }
/* Add a new broker element to a list of brokers */ tRedirectStatus tspAddBrokerToList(tBrokerList **broker_list, char *address, tBrokerAddressType address_type, uint32_t distance) { tBrokerList *new_broker = NULL; /* Some internal error checking */ if (broker_list == NULL) { Display(LOG_LEVEL_1, ELError, "tspAddBrokerToList", GOGO_STR_RDR_ADD_BROKER_INTERNAL_ERR); return TSP_REDIRECT_INTERNAL_ERR; } if (address == NULL) { Display(LOG_LEVEL_1, ELError, "tspAddBrokerToList", GOGO_STR_RDR_ADD_BROKER_INTERNAL_ERR); return TSP_REDIRECT_INTERNAL_ERR; } /* Allocate a new broker element */ if ((new_broker = (tBrokerList *)pal_malloc(sizeof(tBrokerList))) == NULL) { Display(LOG_LEVEL_1, ELError, "tspAddBrokerToList", GOGO_STR_RDR_ADD_BROKER_NO_MEM); return TSP_REDIRECT_CANT_ALLOCATE_MEM; } /* Set the broker address */ pal_snprintf(new_broker->address, MAX_REDIRECT_ADDRESS_LENGTH, "%s", address); /* Validate that the address was set correctly */ if (strlen(new_broker->address) != strlen(address)) { pal_free(new_broker); Display(LOG_LEVEL_1, ELError, "tspAddBrokerToList", GOGO_STR_RDR_ADD_BROKER_ADDRESS_TRUNC); return TSP_REDIRECT_ADDRESS_TRUNCATED; } /* Set the broker distance */ new_broker->distance = distance; /* Set the broker address type */ new_broker->address_type = address_type; /* Add the new broker element at the end of the list */ new_broker->next = NULL; if (*broker_list == NULL) { *broker_list = new_broker; } else { while ((*broker_list)->next != NULL) { broker_list = &((*broker_list)->next); } (*broker_list)->next = new_broker; } return TSP_REDIRECT_OK; }
HM_NODE_DATA_X *hm_alloc_node ( HM_NODE_DATA_X *px_node_data) { HM_NODE_DATA_X *px_new_node = NULL; uint32_t ui_key_len = 0; if (NULL == px_node_data) { HM_LOG_MED("Invalid Args"); goto CLEAN_RETURN; } px_new_node = pal_malloc (sizeof(HM_NODE_DATA_X), NULL); if (NULL == px_new_node) { HM_LOG_MED("pal_malloc failed"); goto CLEAN_RETURN; } (void) pal_memmove(px_new_node, px_node_data, sizeof (*px_new_node)); if (eHM_KEY_TYPE_STRING == px_node_data->e_hm_key_type) { ui_key_len = pal_strlen (px_node_data->u_hm_key.puc_str_key); ui_key_len = ui_key_len + 1; px_new_node->u_hm_key.puc_str_key = pal_malloc (ui_key_len, NULL); if (NULL == px_new_node->u_hm_key.puc_str_key) { pal_free (px_new_node); px_new_node = NULL; goto CLEAN_RETURN; } (void) pal_strncpy (px_new_node->u_hm_key.puc_str_key, px_node_data->u_hm_key.puc_str_key, ui_key_len); } CLEAN_RETURN: return px_new_node; }
/* Sort a list of brokers based on the distance value (roundtrip time) */ tRedirectStatus tspSortBrokerList(tBrokerList **broker_list, tConf *conf, sint32_t broker_count) { tBrokerList *sorted_list = NULL; tBrokerList *current_broker = NULL; tBrokerList *new_element = NULL; Display(LOG_LEVEL_2, ELInfo, "tspSortBrokerList", GOGO_STR_RDR_SORTING_BROKER_LIST); /* Get the distance values */ if (tspGetBrokerDistances(*broker_list, broker_count, conf) != TSP_REDIRECT_OK) { Display(LOG_LEVEL_1, ELError, "tspSortBrokerList", GOGO_STR_RDR_SORT_LIST_CANT_GET_DIST); return TSP_REDIRECT_CANT_GET_DISTANCES; } current_broker = *broker_list; /* For each broker in the original list */ while (current_broker != NULL) { /* Create a new broker element */ if ((new_element = (tBrokerList *)pal_malloc(sizeof(tBrokerList))) == NULL) { tspFreeBrokerList(sorted_list); Display(LOG_LEVEL_1, ELError, "tspSortBrokerList", GOGO_STR_RDR_SORT_LIST_CANT_ALLOC); return TSP_REDIRECT_CANT_ALLOCATE_MEM; } /* Copy the address from the broker in the original list */ strcpy(new_element->address, current_broker->address); /* Copy the distance from the broker in the original list */ new_element->distance = current_broker->distance; /* Copy the address_type as well! */ new_element->address_type = current_broker->address_type; new_element->next = NULL; /* Insert (sorted) the new element in the sorted list */ if (tspInsertInBrokerList(new_element, &sorted_list) != TSP_REDIRECT_OK) { tspFreeBrokerList(sorted_list); Display(LOG_LEVEL_1, ELError, "tspSortBrokerList", GOGO_STR_RDR_SORT_LIST_CANT_INSERT); return TSP_REDIRECT_CANT_INSERT_BROKER_IN_LIST; } /* Move to the next broker in the original list */ current_broker = current_broker->next; } /* Free the original list */ tspFreeBrokerList(*broker_list); /* Replace the original list with the sorted one */ *broker_list = sorted_list; return TSP_REDIRECT_OK; }
/* Create a stat engine for a distance calculation thread */ rttengine_stat_t *createStatEngine() { rttengine_stat_t *engine = NULL; /* Allocate memory */ engine = (rttengine_stat_t *)pal_malloc(sizeof(rttengine_stat_t)); if( engine == NULL ) { return NULL; } /* And zero it */ memset( engine, 0, sizeof(rttengine_stat_t) ); return engine; }
SOCKMON_RET_E dimutex_node_sockmon_active_sock_cbk ( SOCKMON_SOCK_ACTIVITY_STATUS_E e_status, PAL_SOCK_HDL hl_sock_hdl, void *p_app_data) { SOCKMON_RET_E e_sockmon_ret = eSOCKMON_RET_FAILURE; DIMUTEX_RET_E e_error = eDIMUTEX_RET_FAILURE; DIMUTEX_CTXT_X *px_dimutex_ctxt = NULL; DIMUTEX_NODE_SOCK_ACT_DATA_X *px_sock_act_data = NULL; if ((NULL == hl_sock_hdl) || (NULL == p_app_data)) { DMUT_LOG_LOW("Invalid Args"); e_sockmon_ret = eSOCKMON_RET_INVALID_ARGS; goto CLEAN_RETURN; } px_dimutex_ctxt = (DIMUTEX_CTXT_X *) p_app_data; DMUT_LOG_LOW("dimutex_node_sockmon_active_sock_cbk called."); px_sock_act_data = pal_malloc (sizeof(DIMUTEX_NODE_SOCK_ACT_DATA_X), NULL ); px_sock_act_data->x_hdr.ui_msg_id = eDIMUTEX_MSG_ID_LISTENER_SOCK_ACT; px_sock_act_data->x_hdr.ui_msg_pay_len = sizeof(*px_sock_act_data) - sizeof(px_sock_act_data->x_hdr); px_sock_act_data->hl_sock_hdl = hl_sock_hdl; e_error = dimutex_post_msg_to_q ( px_dimutex_ctxt, (uint8_t *) px_sock_act_data, sizeof(*px_sock_act_data)); if (eDIMUTEX_RET_SUCCESS != e_error) { DMUT_LOG_LOW("dimutex_post_msg_to_q failed: %d", e_error); pal_free(px_sock_act_data); px_sock_act_data = NULL; e_sockmon_ret = eSOCKMON_RET_RESOURCE_FAILURE; } else { e_sockmon_ret = eSOCKMON_RET_SUCCESS; } CLEAN_RETURN: return e_sockmon_ret; }
static HM_TABLE_ENTRY_X *hm_get_new_table_entry_from_hash ( HM_CTXT_X *px_hm_ctxt, uint32_t ui_hash) { HM_TABLE_ENTRY_X *px_hm_table_entry = NULL; LIST_RET_E e_list_ret = eLIST_RET_FAILURE; LIST_INIT_PARAMS_X x_init_params = {0}; if (NULL == px_hm_ctxt) { HM_LOG_MED("Invalid Args"); goto CLEAN_RETURN; } px_hm_table_entry = px_hm_ctxt->ppx_hash_table[ui_hash]; if (NULL == px_hm_table_entry) { HM_LOG_HIGH("Table entry @ %d position needs to be allocated", ui_hash); px_hm_table_entry = pal_malloc (sizeof(HM_TABLE_ENTRY_X), NULL); if (NULL == px_hm_table_entry) { HM_LOG_MED("pal_malloc failed"); goto CLEAN_RETURN; } px_hm_ctxt->ppx_hash_table[ui_hash] = px_hm_table_entry; } if (NULL == px_hm_table_entry->hl_list_hdl) { HM_LOG_HIGH("List @ %d position needs to be allocated", ui_hash); x_init_params.ui_list_max_elements = LIST_SIZE_UNLIMITED; e_list_ret = list_create (&(px_hm_table_entry->hl_list_hdl), &x_init_params); if ((eLIST_RET_SUCCESS != e_list_ret) || (NULL == px_hm_table_entry->hl_list_hdl)) { HM_LOG_MED("list_create failed: %d", e_list_ret, px_hm_table_entry->hl_list_hdl); pal_free (px_hm_table_entry); px_hm_table_entry = NULL; } } CLEAN_RETURN: return px_hm_table_entry; }
static DIMUTEX_RET_E dimutex_algo_post_complete_to_main_task ( DIMUTEX_CTXT_X *px_dimutex_ctxt) { DIMUTEX_RET_E e_error = eDIMUTEX_RET_FAILURE; DIMUTEX_ALGO_COMPLETE_X *px_algo_complete = NULL; if (NULL == px_dimutex_ctxt) { DMUT_LOG_LOW("Invalid Args"); e_error = eDIMUTEX_RET_INVALID_ARGS; goto CLEAN_RETURN; } px_algo_complete = pal_malloc (sizeof(DIMUTEX_ALGO_COMPLETE_X), NULL); if (NULL == px_algo_complete) { DMUT_LOG_LOW("pal_malloc failed"); e_error = eDIMUTEX_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } DMUT_LOG_LOW("Posting eDIMUTEX_MSG_ID_ALGO_COMPLETE to myself"); px_algo_complete->x_hdr.ui_msg_id = eDIMUTEX_MSG_ID_ALGO_COMPLETE; px_algo_complete->x_hdr.ui_msg_pay_len = sizeof(*px_algo_complete) - sizeof(px_algo_complete->x_hdr); (void) pal_memmove (&(px_algo_complete->x_stats), &(px_dimutex_ctxt->x_algo.x_algo_stats), sizeof(px_algo_complete->x_stats)); e_error = dimutex_post_msg_to_q (px_dimutex_ctxt, (uint8_t *) px_algo_complete, sizeof(*px_algo_complete)); if (eDIMUTEX_RET_SUCCESS != e_error) { DMUT_LOG_LOW("dimutex_post_msg_to_q failed: %d", e_error); pal_free (px_algo_complete); px_algo_complete = NULL; } else { e_error = eDIMUTEX_RET_SUCCESS; } CLEAN_RETURN: return e_error; }
/****************************** LOCAL FUNCTIONS *******************************/ LIST_RET_E list_create_private ( LIST_CTXT_X **ppx_list_ctxt, LIST_INIT_PARAMS_X *px_init_params) { LIST_RET_E e_error = eLIST_RET_FAILURE; LIST_CTXT_X *px_list_ctxt = NULL; if ((NULL == ppx_list_ctxt) || (NULL == px_init_params)) { LIST_LOG_MED("Invalid Args"); e_error = eLIST_RET_INVALID_ARGS; goto CLEAN_RETURN; } *ppx_list_ctxt = NULL; px_list_ctxt = pal_malloc (sizeof(LIST_CTXT_X), NULL); if (NULL == px_list_ctxt) { LIST_LOG_MED("pal_malloc failed: %p", px_list_ctxt); e_error = eLIST_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } (void) pal_memmove(&(px_list_ctxt->x_init_params), px_init_params, sizeof(px_list_ctxt->x_init_params)); px_list_ctxt->px_head = NULL; px_list_ctxt->px_tail = NULL; px_list_ctxt->ui_node_count = 0; *ppx_list_ctxt = px_list_ctxt; LIST_LOG_HIGH("List of size %d create success", px_init_params->ui_list_max_elements); e_error = eLIST_RET_SUCCESS; CLEAN_RETURN: if (eLIST_RET_SUCCESS != e_error) { if (NULL != px_list_ctxt) { pal_free (px_list_ctxt); px_list_ctxt = NULL; } } return e_error; }
// -------------------------------------------------------------------------- // _create_ka_engine: Allocates the Keepalive engine and initializes it. // // Parameter: // pp_engine: double pointer to the keepalive engine. // // Returned values: // KA_PRIV_SUCCESS: Operation successful. // KA_RESOURCE_STARVATION: Memory allocation error. // KA_INVALID_PARMS: Invalid pp_engine pointer. // ka_priv_ret_t _create_ka_engine( PKA_ENGINE_PARMS* pp_engine ) { if( pp_engine == NULL || *pp_engine != NULL ) { // Invalid double pointer or pointer is not initialized to NULL. return KA_INVALID_PARMS; } *pp_engine = (PKA_ENGINE_PARMS)pal_malloc( sizeof(KA_ENGINE_PARMS) ); if( *pp_engine == NULL ) { // Failed to allocate memory for the keepalive engine. return KA_RESOURCE_STARVATION; } // Initialize the keepalive engine parameters. (*pp_engine)->ka_thread_id = 0; (*pp_engine)->ka_status = KA_STAT_INVALID; (*pp_engine)->p_echo_engine = NULL; return KA_PRIV_SUCCESS; }
/****************************** LOCAL FUNCTIONS *******************************/ CH_IR_RET_E ch_ir_tokenizer_init( CH_IR_TOKENIZER_INIT_PARAMS_X *px_init_params, CH_IR_TOKENIZER_CTXT_X **ppx_tokenizer_ctxt) { CH_IR_RET_E e_ret_val = eCH_IR_RET_FAILURE; CH_IR_TOKENIZER_CTXT_X *px_tokenizer_ctxt = NULL; if ((NULL == px_init_params) || (NULL == ppx_tokenizer_ctxt)) { CH_IR_LOG_MED("Invalid Args"); e_ret_val = eCH_IR_RET_INVALID_ARGS; goto CLEAN_RETURN; } if ((NULL == px_init_params->fn_ch_ir_for_each_token_cbk) || (0 == px_init_params->ui_max_token_len)) { CH_IR_LOG_MED("Invalid Args"); e_ret_val = eCH_IR_RET_INVALID_ARGS; goto CLEAN_RETURN; } px_tokenizer_ctxt = pal_malloc (sizeof(CH_IR_TOKENIZER_CTXT_X), NULL); if (NULL == px_tokenizer_ctxt) { CH_IR_LOG_MED("pal_malloc failed"); e_ret_val = eCH_IR_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } (void) pal_memmove(&(px_tokenizer_ctxt->x_init_params), px_init_params, sizeof(px_tokenizer_ctxt->x_init_params)); *ppx_tokenizer_ctxt = px_tokenizer_ctxt; e_ret_val = eCH_IR_RET_SUCCESS; CLEAN_RETURN: return e_ret_val; }
LIST_NODE_X *list_alloc_node ( LIST_NODE_DATA_X *px_node_data) { LIST_NODE_X *px_node = NULL; if (NULL != px_node_data) { px_node = pal_malloc(sizeof(LIST_NODE_X), NULL); if (NULL != px_node) { (void) pal_memmove(&(px_node->x_node_data), px_node_data, sizeof(px_node->x_node_data)); } else { LIST_LOG_MED("pal_malloc failed: %p", px_node); } } else { LIST_LOG_MED("Invalid Args"); } return px_node; }
static CH_IR_RET_E ch_ir_tokenizer_parse_line( CH_IR_TOKENIZER_CTXT_X *px_tokenizer_ctxt, uint8_t *puc_line, uint8_t *puc_file_path, uint32_t ui_file_idx) { CH_IR_RET_E e_ret_val = eCH_IR_RET_FAILURE; uint8_t uc_c = 0; uint32_t ui_i = 0; bool b_ignore = false; bool b_break = false; uint8_t *puc_token = NULL; uint32_t ui_token_len = 0; bool b_only_numerals = false; if ((NULL == px_tokenizer_ctxt) || (NULL == puc_line) || (NULL == puc_file_path)) { CH_IR_LOG_MED("Invalid Args"); e_ret_val = eCH_IR_RET_INVALID_ARGS; goto CLEAN_RETURN; } puc_token = pal_malloc (px_tokenizer_ctxt->x_init_params.ui_max_token_len, NULL); if (NULL == puc_token) { CH_IR_LOG_MED("pal_malloc failed"); e_ret_val = eCH_IR_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } while (1) { uc_c = puc_line [ui_i]; switch (uc_c) { case '\0': { if (ui_token_len > 0) { puc_token [ui_token_len] = '\0'; if ('\'' == puc_token [0] && '\'' == puc_token [ui_token_len - 1]) { pal_memmove (puc_token, &puc_token [1], ui_token_len - 2); puc_token [ui_token_len - 2] = '\0'; } ch_ir_tokenizer_handle_token (px_tokenizer_ctxt, puc_token, puc_file_path, ui_file_idx); (void) pal_memset (puc_token, 0x00, px_tokenizer_ctxt->x_init_params.ui_max_token_len); ui_token_len = 0; } b_break = true; break; } case '<': { b_ignore = true; break; } case '>': { b_ignore = true; break; } case '.': { if (ui_token_len > 0) { puc_token [ui_token_len] = '\0'; b_only_numerals = ch_ir_tokenizer_does_token_contain_only_numerals (puc_token); if ((true == b_only_numerals) && ('\0' != puc_line [ui_i + 1]) && ((puc_line [ui_i + 1] >= '0') && (puc_line [ui_i + 1] <= '9'))) { /* * Handle the following case: * 1. 10.901 */ puc_token [ui_token_len] = '.'; ui_token_len++; } else { ch_ir_tokenizer_handle_token (px_tokenizer_ctxt, puc_token, puc_file_path, ui_file_idx); (void) pal_memset (puc_token, 0x00, px_tokenizer_ctxt->x_init_params.ui_max_token_len); ui_token_len = 0; } } break; } case ',': case '!': case ' ': case '(': case ')': case '/': /* * All these are considered as delimiters. */ { if (ui_token_len > 0) { puc_token [ui_token_len] = '\0'; if ('\'' == puc_token [0] && '\'' == puc_token [ui_token_len - 1]) { pal_memmove (puc_token, &puc_token [1], ui_token_len - 3); puc_token [ui_token_len - 2] = '\0'; } ch_ir_tokenizer_handle_token (px_tokenizer_ctxt, puc_token, puc_file_path, ui_file_idx); (void) pal_memset (puc_token, 0x00, px_tokenizer_ctxt->x_init_params.ui_max_token_len); ui_token_len = 0; } break; } default: { if (true == b_ignore) { break; } else { puc_token [ui_token_len] = tolower (uc_c); ui_token_len++; } } } if (true == b_break) { break; } ui_i++; } e_ret_val = eCH_IR_RET_SUCCESS; CLEAN_RETURN: if (NULL != puc_token) { pal_free (puc_token); puc_token = NULL; } return e_ret_val; }
/****************************** LOCAL FUNCTIONS *******************************/ CH_IR_RET_E ch_ir_indexer_init( CH_IR_INDEXER_INIT_PARAMS_X *px_init_params, CH_IR_INDEXER_CTXT_X **ppx_indexer_ctxt) { CH_IR_RET_E e_ret_val = eCH_IR_RET_FAILURE; CH_IR_INDEXER_CTXT_X *px_indexer_ctxt = NULL; CH_IR_TOKENIZER_INIT_PARAMS_X x_tokenizer_init_params = {0}; CH_IR_DIR_PARSER_INIT_PARAMS_X x_dir_parser_init_params = {0}; HM_RET_E e_hm_ret = eHM_RET_FAILURE; HM_INIT_PARAMS_X x_hm_init_params = { 0 }; if ((NULL == px_init_params) || (NULL == ppx_indexer_ctxt)) { CH_IR_LOG_MED("Invalid Args"); e_ret_val = eCH_IR_RET_INVALID_ARGS; goto CLEAN_RETURN; } if ((0 == px_init_params->ui_max_filepath_len) || (0 == px_init_params->ui_max_token_len) || (0 == px_init_params->ui_token_hm_table_size) || (0 == px_init_params->ui_postings_hm_table_size)) { CH_IR_LOG_MED("Invalid Args"); e_ret_val = eCH_IR_RET_INVALID_ARGS; goto CLEAN_RETURN; } px_indexer_ctxt = pal_malloc (sizeof(CH_IR_INDEXER_CTXT_X), NULL); if (NULL == px_indexer_ctxt) { CH_IR_LOG_MED("pal_malloc failed"); e_ret_val = eCH_IR_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } (void) pal_memmove(&(px_indexer_ctxt->x_init_params), px_init_params, sizeof(px_indexer_ctxt->x_init_params)); x_tokenizer_init_params.ui_max_token_len = px_init_params->ui_max_token_len; x_tokenizer_init_params.fn_ch_ir_for_each_token_cbk = ch_ir_indexer_for_each_token_cbk; x_tokenizer_init_params.p_app_data = px_indexer_ctxt; e_ret_val = ch_ir_tokenizer_init(&x_tokenizer_init_params, &(px_indexer_ctxt->px_tokenizer_ctxt)); if (eCH_IR_RET_SUCCESS != e_ret_val) { CH_IR_LOG_MED("ch_ir_tokenizer_init failed: %d", e_ret_val); goto CLEAN_RETURN; } x_dir_parser_init_params.ui_max_filepath_len = px_init_params->ui_max_filepath_len; x_dir_parser_init_params.fn_ch_ir_for_each_file_cbk = ch_ir_indexer_for_each_file_cbk; x_dir_parser_init_params.p_app_data = px_indexer_ctxt; e_ret_val = ch_ir_dir_parser_init(&x_dir_parser_init_params, &(px_indexer_ctxt->px_dir_parser_ctxt)); if (eCH_IR_RET_SUCCESS != e_ret_val) { CH_IR_LOG_MED("ch_ir_dir_parser_init failed: %d", e_ret_val); goto CLEAN_RETURN; } if (true == px_init_params->b_ignore_stopwords) { ch_ir_indexer_create_stopwords_cache_hm (px_indexer_ctxt, px_init_params->uca_stopwords_filepath); } x_hm_init_params.e_hm_key_type = eHM_KEY_TYPE_STRING; x_hm_init_params.b_maintain_linked_list = true; x_hm_init_params.ui_linked_list_flags |= eHM_LINKED_LIST_FLAGS_BM_UNSORTED; x_hm_init_params.ui_hm_table_size = px_init_params->ui_token_hm_table_size; e_hm_ret = hm_create (&(px_indexer_ctxt->hl_token_hm), &x_hm_init_params); if (eHM_RET_SUCCESS != e_hm_ret) { CH_IR_LOG_MED("hm_create failed: %d", e_hm_ret); e_ret_val = eCH_IR_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } *ppx_indexer_ctxt = px_indexer_ctxt; e_ret_val = eCH_IR_RET_SUCCESS; CLEAN_RETURN: if (eCH_IR_RET_SUCCESS != e_ret_val) { (void) ch_ir_indexer_deinit(px_indexer_ctxt); } return e_ret_val; }
int main (int argc, char **argv) { APP_RET_E e_main_ret = eAPP_RET_FAILURE; PAL_RET_E e_pal_ret = ePAL_RET_FAILURE; APP_CTXT_X *px_app_ctxt = NULL; bool b_pal_init = false; int32_t i_command = -1; int32_t i_ret = -1; PAL_LOGGER_INIT_PARAMS_X x_logger_params = {false}; e_pal_ret = pal_env_init(); if (ePAL_RET_SUCCESS != e_pal_ret) { goto CLEAN_RETURN; } b_pal_init = true; px_app_ctxt = pal_malloc(sizeof(APP_CTXT_X), NULL); if (NULL == px_app_ctxt) { goto CLEAN_RETURN; } e_main_ret = app_parse_cmd_line (px_app_ctxt, argc, argv); if (eAPP_RET_SUCCESS != e_main_ret) { goto CLEAN_RETURN; } x_logger_params.b_enable_console_logging = (0 == px_app_ctxt->x_app_args.ui_enable_console_logging) ? false : true; x_logger_params.b_enable_file_logging = true; (void) pal_strncpy (x_logger_params.uca_filename_prefix, (uint8_t *) "dimutex_log_node_", sizeof(x_logger_params.uca_filename_prefix)); x_logger_params.ui_file_name_suffix = px_app_ctxt->x_app_args.ui_node_index; pal_logger_env_init(&x_logger_params); e_main_ret = app_env_init (px_app_ctxt); if (eAPP_RET_SUCCESS != e_main_ret) { goto CLEAN_RETURN; } while (1) { i_ret = scanf ("%d", &i_command); (void) i_ret; if (1 == i_command) { break; } } e_main_ret = app_env_deinit (px_app_ctxt); if (eAPP_RET_SUCCESS != e_main_ret) { } pal_logger_env_deinit (); CLEAN_RETURN: if (NULL != px_app_ctxt) { pal_free(px_app_ctxt); px_app_ctxt = NULL; } if (true == b_pal_init) { e_pal_ret = pal_env_deinit(); if (ePAL_RET_SUCCESS != e_pal_ret) { e_main_ret = eAPP_RET_FAILURE; } b_pal_init = false; } return (int) e_main_ret; }
void set_tsp_env_variables( const tConf* pConfig, const tTunnel* pTunnelInfo ) { char buffer[8]; // Specify log verbosity (MAXIMAL). pal_snprintf( buffer, sizeof buffer, "%d", LOG_LEVEL_MAX ); tspSetEnv("TSP_VERBOSE", buffer, 1); // Specify Gateway6 Client installation directory. tspSetEnv("TSP_HOME_DIR", TspHomeDir, 1); // Specify the tunnel mode. tspSetEnv("TSP_TUNNEL_MODE", pTunnelInfo->type, 1); // Specify host type {router, host} tspSetEnv("TSP_HOST_TYPE", pConfig->host_type, 1); // Specify tunnel interface, for setup. if (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6V4) == 0 ) { tspSetEnv("TSP_TUNNEL_INTERFACE", pConfig->if_tunnel_v6v4, 1); gTunnelInfo.eTunnelType = TUNTYPE_V6V4; } else if (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6UDPV4) == 0 ) { tspSetEnv("TSP_TUNNEL_INTERFACE", pConfig->if_tunnel_v6udpv4, 1); gTunnelInfo.eTunnelType = TUNTYPE_V6UDPV4; } #ifdef V4V6_SUPPORT else if (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V4V6) == 0 ) { tspSetEnv("TSP_TUNNEL_INTERFACE", pConfig->if_tunnel_v4v6, 1); gTunnelInfo.eTunnelType = TUNTYPE_V4V6; } #endif /* V4V6_SUPPORT */ // Specify what interface will be used for routing advertizement, // if enabled. tspSetEnv("TSP_HOME_INTERFACE", pConfig->if_prefix, 1); // Specify local endpoint IPv4 address tspSetEnv("TSP_CLIENT_ADDRESS_IPV4", pTunnelInfo->client_address_ipv4, 1); gTunnelInfo.szIPV4AddrLocalEndpoint = pTunnelInfo->client_address_ipv4; // Specify local endpoint IPv6 address tspSetEnv("TSP_CLIENT_ADDRESS_IPV6", pTunnelInfo->client_address_ipv6, 1); gTunnelInfo.szIPV6AddrLocalEndpoint = pTunnelInfo->client_address_ipv6; // Specify local endpoint domain name if( pTunnelInfo->client_dns_name != NULL) { tspSetEnv("TSP_CLIENT_DNS_NAME", pTunnelInfo->client_dns_name, 1); gTunnelInfo.szUserDomain = pTunnelInfo->client_dns_name; } // Specify remote endpoint IPv4 address. tspSetEnv("TSP_SERVER_ADDRESS_IPV4", pTunnelInfo->server_address_ipv4, 1); gTunnelInfo.szIPV4AddrRemoteEndpoint = pTunnelInfo->server_address_ipv4; // Specify remote endpoint IPv6 address. tspSetEnv("TSP_SERVER_ADDRESS_IPV6", pTunnelInfo->server_address_ipv6, 1); gTunnelInfo.szIPV6AddrRemoteEndpoint = pTunnelInfo->server_address_ipv6; // Specify prefix for tunnel endpoint. if ((pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6V4) == 0) || (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6UDPV4) == 0)) tspSetEnv("TSP_TUNNEL_PREFIXLEN", "128", 1); #ifdef V4V6_SUPPORT else tspSetEnv("TSP_TUNNEL_PREFIXLEN", "32", 1); #endif /* V4V6_SUPPORT */ // Free and clear delegated prefix from tunnel info. if( gTunnelInfo.szDelegatedPrefix != NULL ) { pal_free( gTunnelInfo.szDelegatedPrefix ); gTunnelInfo.szDelegatedPrefix = NULL; } // Have we been allocated a prefix for routing advertizement..? if( pTunnelInfo->prefix != NULL ) { char chPrefix[128]; size_t len, sep; /* Compute the number of characters that are significant out of the prefix. */ /* This is meaningful only for IPv6 prefixes; no contraction is possible for IPv4. */ if ((pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6V4) == 0) || (pal_strcasecmp(pTunnelInfo->type, STR_XML_TUNNELMODE_V6UDPV4) == 0)) { len = (atoi(pTunnelInfo->prefix_length) % 16) ? (atoi(pTunnelInfo->prefix_length) / 16 + 1) * 4 : atoi(pTunnelInfo->prefix_length) / 16 * 4; sep = (atoi(pTunnelInfo->prefix_length) % 16) ? (atoi(pTunnelInfo->prefix_length) / 16) : (atoi(pTunnelInfo->prefix_length) / 16) -1; } else { len = pal_strlen( pTunnelInfo->prefix ); sep = 0; } memset(chPrefix, 0, 128); memcpy(chPrefix, pTunnelInfo->prefix, len+sep); // Specify delegated prefix for routing advertizement, if enabled. tspSetEnv("TSP_PREFIX", chPrefix, 1); gTunnelInfo.szDelegatedPrefix = (char*) pal_malloc( pal_strlen(chPrefix) + 10/*To append prefix_length*/ ); strcpy( gTunnelInfo.szDelegatedPrefix, chPrefix ); // Specify prefix length for routing advertizement, if enabled. tspSetEnv("TSP_PREFIXLEN", pTunnelInfo->prefix_length, 1); strcat( gTunnelInfo.szDelegatedPrefix, "/" ); strcat( gTunnelInfo.szDelegatedPrefix, pTunnelInfo->prefix_length ); } }
// -------------------------------------------------------------------------- // IEE_init: ICMP Echo Engine initialisation routine. // // Parameters: // pp_config: Opaque double pointer to a ICMP_ECHO_ENGINE_PARMS structure. // eng_mode: The mode of the ICMP Echo Engine. // send_interval: Fixed interval, in miliseconds, at which ICMP echo // requests will be issued. // echo_num: Number of ICMP echo requests to issue(0=infinite). // echo_timeout: Number of miliseconds after which an unanswered ICMP // echo request will be marked as timed out. // echo_timeout_threshold: Number of consecutive timed-out ICMP echo // requests to declare a general echo timeout. // src: Source address used for sending ICMP echo requests. // dst: Destination address at which ICMP echo requests will be sent. // family: address family (INET or INET6) // // Return values: // IEE_SUCCESS on success. // IEE_INVALID_PARMS if invalid pp_config. // iee_ret_t IEE_init( void** pp_config, iee_mode_t eng_mode, uint32_t send_interval, uint32_t echo_num, uint32_t echo_timeout, uint8_t echo_timeout_threshold, char* src, char* dst, sint32_t af, iee_send_clbk send_clbk, iee_recv_clbk recv_clbk ) { PICMP_ECHO_ENGINE_PARMS p_engine = NULL; // Verify input parameters. if( pp_config == NULL || *pp_config != NULL || dst == NULL ) { // Error: bad input parameters. return IEE_INVALID_PARMS; } // Reserve memory for the engine parameters *pp_config = pal_malloc( sizeof(ICMP_ECHO_ENGINE_PARMS) ); p_engine = (PICMP_ECHO_ENGINE_PARMS)*pp_config; if( p_engine == NULL ) { // Error: Not enough memory for structure. return IEE_RESOURCE_STARVATION; } // Initialize engine structure with input parameters. memset( p_engine, 0, sizeof(ICMP_ECHO_ENGINE_PARMS) ); p_engine->send_interval = send_interval; p_engine->echo_num = echo_num; p_engine->echo_timeout = echo_timeout; // Not used in ACD p_engine->echo_timeout_threshold = echo_timeout_threshold; p_engine->eng_mode = eng_mode; // Initialize engine variables. p_engine->eng_ongoing = 1; p_engine->count_send = 0; p_engine->count_late = 0; p_engine->count_ontime = 0; p_engine->count_consec_late = 0; p_engine->event_list = NULL; // Set engine callback functions. p_engine->clbk_send = send_clbk; p_engine->clbk_recv = recv_clbk; // Initialize engine socket variables. p_engine->icmp_echo_id = pal_getpid(); p_engine->icmp_saf = af; switch( p_engine->icmp_saf ) { case AF_INET: if( pal_inet_pton( AF_INET, src, &p_engine->echo_addr_src.in4.sin_addr ) <= 0 ) { // Bad IPv4 address in 'src'. pal_free( p_engine ); return IEE_INVALID_PARMS; } p_engine->echo_addr_src.in4.sin_family = AF_INET; if( pal_inet_pton( AF_INET, dst, &p_engine->echo_addr_dst.in4.sin_addr ) <= 0 ) { // Bad IPv4 address in 'dst'. pal_free( p_engine ); return IEE_INVALID_PARMS; } p_engine->echo_addr_dst.in4.sin_family = AF_INET; p_engine->icmp_sfd = pal_socket( AF_INET, SOCK_RAW, IPPROTO_ICMP ); break; case AF_INET6: if( pal_inet_pton( AF_INET6, src, &p_engine->echo_addr_src.in6.sin6_addr ) <= 0 ) { // Bad IPv6 address in 'src'. pal_free( p_engine ); return IEE_INVALID_PARMS; } p_engine->echo_addr_src.in6.sin6_family = AF_INET6; if( pal_inet_pton( AF_INET6, dst, &p_engine->echo_addr_dst.in6.sin6_addr ) <= 0 ) { // Bad IPv6 address in 'dst'. pal_free( p_engine ); return IEE_INVALID_PARMS; } p_engine->echo_addr_dst.in6.sin6_family = AF_INET6; p_engine->icmp_sfd = pal_socket( AF_INET6, SOCK_RAW, IPPROTO_ICMPV6 ); break; default: // ERROR! Bad address family! pal_free( p_engine ); return IEE_INVALID_PARMS; } // Verify that the socket created is valid. if( p_engine->icmp_sfd == -1 ) { // Failed to open a socket descriptor. pal_free( p_engine ); return IEE_GENERAL_ECHO_ERROR; } return IEE_SUCCESS; }
HM_RET_E hm_create_resources ( HM_CTXT_X *px_hm_ctxt) { HM_RET_E e_error = eHM_RET_FAILURE; PAL_RET_E e_pal_ret = ePAL_RET_FAILURE; uint32_t ui_alloc_size = 0; PAL_MUTEX_CREATE_PARAM_X x_mutex_param = {{0}}; LIST_RET_E e_list_ret = eLIST_RET_FAILURE; LIST_INIT_PARAMS_X x_list_params = {0}; if (NULL == px_hm_ctxt) { HM_LOG_MED("Invalid Args"); e_error = eHM_RET_INVALID_ARGS; goto CLEAN_RETURN; } ui_alloc_size = px_hm_ctxt->x_init_params.ui_hm_table_size * sizeof(HM_TABLE_ENTRY_X *); px_hm_ctxt->ppx_hash_table = pal_malloc (ui_alloc_size, NULL ); if (NULL == px_hm_ctxt->ppx_hash_table) { HM_LOG_MED("pal_malloc failed"); e_error = eHM_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } if ((true == px_hm_ctxt->x_init_params.b_thread_safe) && (eHM_THREAD_SAFE_FLAGS_BM_MAP_LEVEL & px_hm_ctxt->x_init_params.ui_thread_safe_flags)) { e_pal_ret = pal_mutex_create (&(px_hm_ctxt->hl_mutex_hdl), &x_mutex_param); if ((ePAL_RET_SUCCESS != e_pal_ret) || (NULL == px_hm_ctxt->hl_mutex_hdl)) { HM_LOG_MED("pal_mutex_create failed: %d", e_pal_ret); e_error = eHM_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } else { e_error = eHM_RET_SUCCESS; } } else { e_error = eHM_RET_SUCCESS; } if (true == px_hm_ctxt->x_init_params.b_maintain_linked_list) { px_hm_ctxt->px_link_list_ctxt = pal_malloc (sizeof(HM_LINK_LIST_CTXT_X), NULL); if (NULL == px_hm_ctxt->px_link_list_ctxt) { HM_LOG_MED("pal_malloc failed"); e_error = eHM_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } x_list_params.ui_list_max_elements = LIST_SIZE_UNLIMITED; e_list_ret = list_create(&(px_hm_ctxt->px_link_list_ctxt->hl_list_hdl), &x_list_params); if ((eLIST_RET_SUCCESS != e_list_ret) || (NULL == px_hm_ctxt->px_link_list_ctxt->hl_list_hdl)) { HM_LOG_MED("list_create failed: %d", e_list_ret, px_hm_ctxt->px_link_list_ctxt->hl_list_hdl); e_error = eHM_RET_RESOURCE_FAILURE; goto CLEAN_RETURN; } else { e_error = eHM_RET_SUCCESS; } } else { e_error = eHM_RET_SUCCESS; } CLEAN_RETURN: return e_error; }
// -------------------------------------------------------------------------- // AuthDIGEST_MD5: Performs a Digest-MD5 authentication with the server. // gogoc_status AuthDIGEST_MD5(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list, int version_index) { char Buffer[4096], Response[33], cResponse[33], *ChallengeString; char string[] = "AUTHENTICATE DIGEST-MD5\r\n"; char BufferIn[REDIRECT_RECEIVE_BUFFER_SIZE]; time_t cnonce = pal_time(NULL); tChallenge c; sint32_t tsp_status; // Send authentication mode. memset(BufferIn, 0, sizeof(BufferIn)); if( nt->netsendrecv(socket, string, sizeof(string), BufferIn, sizeof(BufferIn)) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_NET_FAIL_RW_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(BufferIn); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } // Check for error in status. if( tsp_status == TSP_PROTOCOL_AUTH_FAILED ) { // Failed authentication. Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); } // Allocate memory for challenge string. if( (ChallengeString = pal_malloc(pal_strlen(BufferIn) + 1)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } base64decode(ChallengeString, BufferIn); ExtractChallenge(&c, ChallengeString); pal_free(ChallengeString); { /*-----------------------------------------------------------*/ /* Extract from : RFC 2831 Digest SASL Mechanism Let H(s) be the 16 octet MD5 hash [RFC 1321] of the octet string s. Let KD(k, s) be H({k, ":", s}), i.e., the 16 octet hash of the string k, a colon and the string s. Let HEX(n) be the representation of the 16 octet MD5 hash n as a string of 32 hex digits (with alphabetic characters always in lower case, since MD5 is case sensitive). response-value = HEX( KD ( HEX(H(A1)), { nonce-value, ":" nc-value, ":", cnonce-value, ":", qop-value, ":", HEX(H(A2)) })) If authzid is not specified, then A1 is A1 = { H( { username-value, ":", realm-value, ":", passwd } ), ":", nonce-value, ":", cnonce-value } If the "qop" directive's value is "auth", then A2 is: A2 = { "AUTHENTICATE:", digest-uri-value } */ char *A1_1Fmt = "%s:%s:%s", #ifndef WIN32 *A1Fmt = ":%s:%lu", *ChallRespFmt = "%s:%s:00000001:%lu:%s:%s", *ResponseFmt = "charset=%s,username=\"%s\",realm=\"%s\",nonce=\"%s\",nc=00000001,cnonce=\"%lu\",digest-uri=\"tsp/%s\",response=%s,qop=auth", #else // 64 bit version. *A1Fmt = ":%s:%I64d", *ChallRespFmt = "%s:%s:00000001:%I64d:%s:%s", *ResponseFmt = "charset=%s,username=\"%s\",realm=\"%s\",nonce=\"%s\",nc=00000001,cnonce=\"%I64d\",digest-uri=\"tsp/%s\",response=%s,qop=auth", #endif *A2Fmt = "%s:tsp/%s", A1[33], A1_1[33], A2[33], cA2[33], *String; size_t len; /*-----------------------------------------------------------*/ /* Build HEX(H(A2)) & HEX(H(cA2)) */ len = pal_strlen(A2Fmt) + 12 /* AUTHENTICATE */ + pal_strlen(conf->server) + 1; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, A2Fmt, "AUTHENTICATE", conf->server); #if defined(_DEBUG) || defined(DEBUG) printf("A2 = %s\n", String); #endif strncpy(A2, md5(String, pal_strlen(String)), 33); pal_snprintf(String, len, A2Fmt, "", conf->server); #if defined(_DEBUG) || defined(DEBUG) printf("cA2 = %s\n", String); #endif strncpy(cA2, md5(String, pal_strlen(String)), 33); pal_free(String); /*-----------------------------------------------------------*/ /* Build HEX(H(A1)) */ /* A1_1 = { username-value, ":", realm-value, ":", passwd } */ /* A1 = { H( A1_1 ), ":", nonce-value, ":", cnonce-value } */ len = pal_strlen(A1_1Fmt) + pal_strlen(conf->userid) + pal_strlen(c.realm) + pal_strlen(conf->passwd) + 1; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, A1_1Fmt, conf->userid, c.realm, conf->passwd); #if defined(_DEBUG) || defined(DEBUG) printf("A1_1 = %s\n", String); #endif md5digest(String, pal_strlen(String), A1_1); pal_free(String); len = 16 /* A1_1 */ + 1 + pal_strlen(c.nonce) + 16 /* cnonce */ + 1; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } memcpy(String, A1_1, 16); pal_snprintf(String + 16, len - 16, A1Fmt, c.nonce, cnonce); #ifdef SUPPORT_MD5_BUG1455 A1_1[16] = '\0'; if ((pal_strlen(A1_1) < 16) && !((pal_strlen(TSPProtoVerStr[version_index]) > 5) || (strcmp(TSPProtoVerStr[version_index], CLIENT_VERSION_STRING_2_0_0) > 0))) strncpy(A1, md5(String, pal_strlen(String)), 33); else #endif /* SUPPORT_MD5_BUG1455 */ strncpy(A1, md5(String, 16 + pal_strlen(String + 16)), 33); pal_free(String); #if defined(_DEBUG) || defined(DEBUG) printf("A1 = [%s]\n", A1); #endif /*-----------------------------------------------------------*/ /* Build server's and client's challenge responses */ len = pal_strlen(ChallRespFmt) + 32 /* md5(A1) */ + pal_strlen(c.nonce) +16 /* cnonce */ + pal_strlen(c.qop) + 32 /* md5(A2) */ + 1; if((String = pal_malloc(len)) == NULL) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, ChallRespFmt, A1, c.nonce, cnonce, c.qop, A2); #if defined(_DEBUG) || defined(DEBUG) printf("Response = [%s]\n", String); #endif strncpy(Response, md5(String, pal_strlen(String)), 33); #if defined(_DEBUG) || defined(DEBUG) printf("MD5 Response = %s\n", Response); #endif pal_snprintf(String, len, ChallRespFmt, A1, c.nonce, cnonce, c.qop, cA2); #if defined(_DEBUG) || defined(DEBUG) printf("cResponse = [%s]\n", String); #endif strncpy(cResponse, md5(String, pal_strlen(String)), 33); #if defined(_DEBUG) || defined(DEBUG) printf("MD5 cResponse = %s\n", cResponse); #endif pal_free(String); /*-----------------------------------------------------------*/ /* Build Response */ { char userid[512]; // UserId is theorically limited to 253 chars. char * cc; size_t i; // Escape malicious " and \ from conf->userid. for(cc=conf->userid, i=0; *cc && i<512; cc++, i++) { // Prepend a backslash (\). if( *cc == '"' || *cc == '\\' ) userid[i++] = '\\'; // Copy character. userid[i] = *cc; } userid[i] = '\0'; len = pal_strlen(ResponseFmt) + pal_strlen(c.charset) + pal_strlen(userid) + pal_strlen(c.realm) + pal_strlen(c.nonce) + 16 /*cnonce*/ + pal_strlen(conf->server) + 32 /* md5 response */; if( (String = pal_malloc(len)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } pal_snprintf(String, len, ResponseFmt, c.charset, userid, c.realm, c.nonce, cnonce, conf->server, Response); memset(Buffer, 0, sizeof(Buffer)); base64encode(Buffer, String, (int)pal_strlen(String)); pal_free(String); } } // Send authentication data. memset(BufferIn, 0, sizeof(BufferIn)); if( nt->netprintf(socket, BufferIn, sizeof(BufferIn), "%s\r\n", Buffer) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_NET_FAIL_W_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(BufferIn); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } /*-----------------------------------------------------------*/ /* Verify server response */ if( tsp_status == TSP_PROTOCOL_AUTH_FAILED ) { // Failed authentication. Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); } if( (ChallengeString = pal_malloc(pal_strlen(BufferIn) + 1)) == NULL ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_GEN_MALLOC_ERROR); return make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); } base64decode(ChallengeString, BufferIn); ExtractChallenge(&c, ChallengeString); pal_free(ChallengeString); if( memcmp(c.rspauth, cResponse, 32) ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_MISC_INVALID_MD5_RESPONSE); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); } // Receive reply. if( nt->netrecv(socket, Buffer, sizeof(Buffer) ) == -1 ) { Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_NET_FAIL_R_SOCKET); return make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); } tsp_status = tspGetStatusCode(Buffer); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(Buffer, conf, broker_list) == TSP_REDIRECT_OK ) { // Return a REDIRECT event. return make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. return make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } } // Check if authentication was successful. switch( tsp_status ) { case TSP_PROTOCOL_SUCCESS: break; case TSP_PROTOCOL_AUTH_FAILED: Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_AUTH_FAILED_USER, conf->userid); return make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); default: Display(LOG_LEVEL_1, ELError, "AuthDIGEST_MD5", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status)); return make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR); } // Successful MD5 authentication. return make_status(CTX_TSPAUTHENTICATION, SUCCESS); }
static int is_dsakey_in_keyfile(DSA *dsa_1, char *host, char *filename) { FILE *fp = NULL; char *line_buf = NULL; char *str = NULL; char *str_base64 = NULL; Buffer keyfile_buf; BIGNUM *bn_p = NULL; BIGNUM *bn_q = NULL; BIGNUM *bn_g = NULL; BIGNUM *bn_pub_key = NULL; int ret = 1; size_t str_size = 0; int i; if (!dsa_1 || !host || !filename) return 0; memset(&keyfile_buf, 0, sizeof(keyfile_buf)); /* Open the keyfile */ if ( (fp = fopen(filename, "r")) == NULL) { /* no key file */ ret = 1; goto is_dsakey_in_keyfile_cleanup; } /* Get memory for a line buffer */ if ( (line_buf = pal_malloc(sizeof(char) * 4096)) == NULL) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } while (freadline(line_buf, 4095, fp) != EOF) { int len; str_base64 = strtok(line_buf, " "); if (strcmp(host, str_base64) != 0) continue; /* We got a match on the hostname * Now we assemble a DSA object * with what we have in the buffer */ str_base64 = strtok(NULL, " "); if (strcmp("ssh-dss", str_base64) != 0) continue; /* We got a match on the key type as well, going on */ str_base64 = strtok(NULL, " "); /* * Get the base64 data * and discard ssh-dss first */ str_size = pal_strlen(str_base64) * sizeof(char); if ( (str = pal_malloc(str_size)) == NULL) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } if ( (len = base64decode(str, str_base64)) < 1) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } /* Fill a buffer structure with this data */ buffer_init(&keyfile_buf); if (keyfile_buf.buf == NULL) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } buffer_append(&keyfile_buf, str, str_size); /* Now get some BN filled with the data * from the buffer and compare * those with what we got in the incoming * dsa object. */ bn_p = BN_new(); bn_q = BN_new(); bn_g = BN_new(); bn_pub_key = BN_new(); if (bn_p == NULL || bn_q == NULL || bn_g == NULL || bn_pub_key == NULL) { ret = 0; goto is_dsakey_in_keyfile_cleanup; } /* String is skipped XXX */ buffer_get_string(&keyfile_buf, (unsigned int*)&i); // Bogus i returns the string length, not used buffer_get_bignum(&keyfile_buf, bn_p); buffer_get_bignum(&keyfile_buf, bn_q); buffer_get_bignum(&keyfile_buf, bn_g); buffer_get_bignum(&keyfile_buf, bn_pub_key); if ( !BN_cmp(dsa_1->p, bn_p) && !BN_cmp(dsa_1->q, bn_q) && !BN_cmp(dsa_1->g, bn_g) && !BN_cmp(dsa_1->pub_key, bn_pub_key) ) ret = 2; else ret = 3; } is_dsakey_in_keyfile_cleanup: if (str) pal_free(str); if (line_buf) pal_free(line_buf); if (fp) fclose(fp); if (bn_p) BN_clear_free(bn_p); if (bn_q) BN_clear_free(bn_q); if (bn_g) BN_clear_free(bn_g); if (bn_pub_key) BN_clear_free(bn_pub_key); if (keyfile_buf.buf) buffer_free(&keyfile_buf); return ret; }
/** Add a DSA key to the tspc key file * * @param dsa the DSA param pointer filled with our key info * @param host the hostname of the corresponding broker * @param filename the keyfile to use * * @return 0 if error * 1 if ok * */ int add_dsakey_to_keyfile(DSA *dsa, char *host, char *filename, tBoolean autoaccept) { FILE *fp = NULL; Buffer buf; char *str = NULL; int ret = 0; switch (is_dsakey_in_keyfile(dsa, host, filename)) { case 0: Display(LOG_LEVEL_3, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_ERR_IN_KEY_VERIF); Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED); break; case 1: /* not in, we add and continue */ #if defined(WIN32) && !defined(WINCE) // When running as a service we can't ask user // permission. Compromise and accept the key auto // if (!IsService && !autoaccept) { #else if (!autoaccept) { #endif if (!ask(GOGO_STR_UNKNOWN_HOST_ADD_KEY, host)) { Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED_USER); break; } } else Display(LOG_LEVEL_1, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_SERVER_KEY_AUTO_ADDED); Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_ACCEPTED_ADDED); buffer_init(&buf); if (buf.buf == NULL) break; buffer_put_cstring(&buf, "ssh-dss"); buffer_put_bignum(&buf, dsa->p); buffer_put_bignum(&buf, dsa->q); buffer_put_bignum(&buf, dsa->g); buffer_put_bignum(&buf, dsa->pub_key); if ( (str = pal_malloc(2 * buffer_len(&buf))) == NULL) break; if ( (base64encode(str, buffer_ptr(&buf), (int) buffer_len(&buf))) < 1) break; fp = fopen(filename, "a"); if (fp) { fprintf(fp, "%s ssh-dss %s\n", host, str); fclose(fp); ret = 1; } buffer_free(&buf); pal_free(str); break; case 2: /* in and matching correctly, hurray */ Display(LOG_LEVEL_2, ELInfo, TSP_AUTH_PASSDSS_STRING, GOGO_STR_MATCHING_KEY_FOUND_USED); ret = 1; break; case 3: /* in and NOT matching correctly */ Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_WARN_STORED_LOCAL_KEY_NO_MATCH, filename, host); Display(LOG_LEVEL_3, ELWarning, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SERVER_KEY_REJECTED); ret = 0; break; } return ret; } /** * Authenticate to the Migration Broker using PASSDSS-3DES-1 * * Buf_H will contain the data used to validate the server * signature. The data is a concatenation of the following parameters, * in that order: * azname,authname,DH_public_key,pklength,"ssh-dss",p,q,g,z,Y,ssecmask,sbuflen,dh_K * * @param socket * @param user * @param passwd * @param host * @param nt * * @return * * @todo DH public key validation (RFC2631, 2.1.5) * @todo Local storage for server public keys * */ gogoc_status AuthPASSDSS_3DES_1(pal_socket_t socket, net_tools_t *nt, tConf *conf, tBrokerList **broker_list) { DH *dh = NULL; /**< client DH key used to exchange key with server */ DSA *dsa = NULL; /**< Remote server DSA key public information */ DSA_SIG *sig = NULL; /**< DSA signature */ char authenticate[] = "AUTHENTICATE PASSDSS-3DES-1\r\n"; char *BufferIn = NULL; char *BufferOut = NULL; char *BufferPtr = NULL; Buffer BufH; /**< Buffer to hold data used for signature. */ Buffer BufSpace; /**< Space to hold data before/after base64 conversion */ Buffer *Buf_H = &BufH; Buffer *Buf_Space = &BufSpace; BIO *bio_rw = NULL; /**< Memory buffer bio */ BIO *b64= NULL; /**< Base64 bio */ BIO *cipher = NULL; /**< Symmetric crypto bio */ BIGNUM *server_pubkey = NULL; /**< received server public DH key */ BIGNUM *dh_K = NULL; /**< DH computed shared secret */ u_char hash[20]; /**< SHA1 hash */ u_char enc_key[24]; /**< encryption key (3des) */ u_char enc_iv[8]; /**< initialization vector (3des) */ u_char int_key[20]; /**< cs integrity key */ u_char tmphash[40]; /**< temporary hash storage */ u_char hmac[EVP_MAX_MD_SIZE]; /**< HMAC for integrity of sent data (step L) */ int pklength = 0; /**< length of SSH-style DSA server public key */ int ssecmask = 0; /**< SASL security layers offered */ int sbuflen = 0; /**< maximum server security layer block size */ char *s = NULL; u_char num[3]; /**< Array to manupulate 3 octet number (sbuflen) */ /* Temporary variables */ int buflen, readlen, keysize, siglength; gogoc_status status = STATUS_SUCCESS_INIT; sint32_t tsp_status; /* From draft-newman-sasl-passdss-01. "This group was taken from the * ISAKMP/Oakley specification, and was originally generated by * Richard Schroeppel at the University of Arizona. Properties of * this prime are described in [Orm96]" */ /* RFC2409, DH group 2 (second Oakley group) */ static char *dh_group2= "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"; static unsigned char dh_g[]={ 0x02, }; /* Initialize Diffie Hellman variables */ if ((dh = DH_new()) == NULL || (server_pubkey = BN_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Convert dh_group2 and dh_g to BIGNUM type */ BN_hex2bn(&dh->p, dh_group2); dh->g = BN_bin2bn(dh_g,sizeof(dh_g),NULL); if ((dh->p == NULL) || (dh->g == NULL)) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_INITIALIZATION_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } if ((dh_K = BN_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Reserve storage for DSA key */ if ((dsa = DSA_new()) == NULL || (dsa->p = BN_new()) == NULL || (dsa->q = BN_new()) == NULL || (dsa->g = BN_new()) == NULL || (dsa->pub_key = BN_new()) == NULL || (dsa->priv_key = BN_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Allocate memory for DSA signature */ if ((sig = DSA_SIG_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Initialize data buffers */ BufferIn = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE); BufferOut = calloc(1, TSP_AUTH_PASSDSS_BUFFERSIZE); if ((BufferIn == NULL) || (BufferOut == NULL)) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } buffer_init(Buf_Space); buffer_init(Buf_H); if (Buf_Space->buf == NULL || Buf_H->buf == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Create a read/write memory BIO. Memory is segment is * created and resized as needed. When BIO is destroyed, the * memory is freed. */ bio_rw = BIO_new(BIO_s_mem()); /* Create a base64 BIO filter */ b64 = BIO_new(BIO_f_base64()); if ((bio_rw == NULL) || (b64 == NULL)) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Compute the Diffie-Hellman public value "X" as follows. If X has a value of 0, repeat. x X = g mod n where g = dh_g = 2 n = dh_group2 x = DH secret key X = DH public key */ if (DH_generate_key(dh) == 0) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_GEN_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } /* Validate DH public key (RFC2631, 2.1.5) */ /* Send message with SASL mechanism identifier */ if ( nt->netsend(socket, authenticate, sizeof(authenticate)) == -1 ) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_W_SOCKET); status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); goto error; } /* First PASSDSS message from client to server: string azname ; the user name to login as, may be empty if same as authentication name string authname ; the authentication name mpint X ; Diffie-Hellman parameter X */ /* azname is empty. Just insert a string length zero */ buffer_put_int(Buf_Space, 0); /* authname */ buffer_put_cstring(Buf_Space, conf->userid); /* DH public key */ buffer_put_bignum(Buf_Space, dh->pub_key); /* At this point, save the buffer into Buf_H. Used later for * signature verification. */ buffer_append(Buf_H, buffer_ptr(Buf_Space), buffer_len(Buf_Space)); /* Push base64 filter */ BIO_push(b64, bio_rw); /* no newline */ BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); /* Write Buffer content into bio_rw. Buffer will be base64 * encoded. */ BIO_write(b64, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space)); BIO_flush(b64); /* Get pointer to the result */ buflen = BIO_get_mem_data(bio_rw, &BufferPtr); // Send data to server, save response in BufferIn. if((readlen = nt->netsendrecv(socket, BufferPtr, buflen, BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET); status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); goto error; } /* remove base64 filter */ BIO_pop(bio_rw); buffer_clear(Buf_Space); buflen = 0; /* Decode response (base64) and extract server response * * The response format is as follows: uint32 pklength ; length of SSH-style DSA server public key (number of bytes up to y, inclusively) string "ssh-dss" ; constant string "ssh-dss" (lower case) mpint p ; DSA public key parameters mpint q mpint g mpint z (y in draft) mpint Y ; Diffie-Hellman parameter Y OCTET ssecmask ; SASL security layers offered 3 OCTET sbuflen ; maximum server security layer block size uint32 siglength ; length of SSH-style dss signature (number of bytes up to s inclusively) string "ssh-dss" ; constant string "ssh-dss" (lower case) mpint r ; DSA signature parameters mpint s */ buflen = base64decode(BufferOut, BufferIn); buffer_append(Buf_Space, BufferOut, buflen); /* Get pklength */ pklength = buffer_get_int(Buf_Space); /* Assuming that * p, g, and y are 512 bits, * q is 160 bits, * "ssh-dss" is 7 bytes * pklength should be at least 240 bytes. */ if (pklength < 240) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } /* Make a copy of (pklength|"ssh-dss"|p|q|g|z) in Buf_H */ /* Add pklength */ buffer_put_int(Buf_H, pklength); /* Add "ssh-dss"|p|q|g|z */ buffer_append(Buf_H, buffer_ptr(Buf_Space), pklength); /* Get "ssh-dss" string */ s = buffer_get_string(Buf_Space, (unsigned int*)&buflen); pal_free(s); s = NULL; /* Get p */ buffer_get_bignum(Buf_Space, dsa->p); /* Get q */ buffer_get_bignum(Buf_Space, dsa->q); /* Get g */ buffer_get_bignum(Buf_Space, dsa->g); /* Get z (pub_key) */ buffer_get_bignum(Buf_Space, dsa->pub_key); /* Get DH public key */ buffer_get_bignum(Buf_Space, server_pubkey); /* Copy in Buf_H for signature verification later */ buffer_put_bignum(Buf_H, server_pubkey); /* Buffer now points at ssecmask (1 octet), followed by * sbuflen (3 octets). Make a copy of these 4 octets in Buf_H * now, then extract these values. */ buffer_append(Buf_H, buffer_ptr(Buf_Space), 4); /* Get ssecmask */ ssecmask = buffer_get_octet(Buf_Space); /* Get sbuflen * Big endian binary unsigned integer */ buffer_get(Buf_Space, (char *)num, 3); sbuflen = (((u_long)(u_char)(num)[0] << 16) | ((u_long)(u_char)(num)[1] << 8) | ((u_long)(u_char)(num)[2])); /* DSS signature */ /* Get siglength */ siglength = buffer_get_int(Buf_Space); /* r and s are 20 bytes each, encoded as mpint (2*24) * "ssh-dss" is 7 bytes + int32 siglength should be >= 59 * octets (mpint may have leading zero byte) */ if (siglength < 59) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_RCVD_DATA_INVALID); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } /* Get "ssh-dss" string */ s = buffer_get_string(Buf_Space, (unsigned int*)&buflen); pal_free(s); s = NULL; /* Get DSA signature r and s*/ if ((sig->r= BN_new()) == NULL || (sig->s = BN_new()) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } /* Get r */ buffer_get_bignum(Buf_Space, sig->r); /* Get s */ buffer_get_bignum(Buf_Space, sig->s); /* Validate server DH public key (RFC2631, 2.1.5) */ { if( !add_dsakey_to_keyfile(dsa, conf->server, TSPC_DSA_KEYFILE, conf->no_questions) ) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_KEY_VERIF_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } } /* Verify that DSA public key belongs to server */ /* Compute DH shared secret */ if ((s = calloc(1, DH_size(dh))) == NULL) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_GEN_MALLOC_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_MEMORY_STARVATION); goto error; } if( (keysize = DH_compute_key((unsigned char*)s, server_pubkey, dh)) < 0 ) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_SHARED_COMPUTE_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; } BN_bin2bn((const unsigned char*)s, keysize, dh_K); memset(s, 0, keysize); pal_free(s); s = NULL; Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DH_SHARED_KEY, BN_bn2hex(dh_K)); /* Append dh_K in to complete the buffer. Use Buffer to hold * result to keep Bf_H intact, since to will be used (without * dh_K) to compute HMAC for packet integrity. */ buffer_clear(Buf_Space); buffer_append(Buf_Space, buffer_ptr(Buf_H), buffer_len(Buf_H)); buffer_put_bignum(Buf_Space, dh_K); /* Compute SHA1 hash of Buffer */ SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), hash); /* Debug information available at level 4 */ { BIGNUM *h; h = BN_bin2bn(hash, 20, NULL); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SIGNED_HASH, BN_bn2hex(h)); BN_free(h); } Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DSA_SIGN_R, BN_bn2hex(sig->r)); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_DSA_SIGN_S, BN_bn2hex(sig->s)); // Verify that the DSS signature is a signature of hash. switch( DSA_do_verify(hash, sizeof(hash), sig, dsa) ) { case 0: Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_BAD_SIG_FROM_SERVER); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; break; /* NOTREACHED */ case 1: /* correct signature */ break; default: /* -1 on error */ Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, GOGO_STR_SIG_VERIF_ERROR); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; break; /* NOTREACHED */ } /* Step I: Compute 3DES key and iv */ /* cs-encryption-iv = SHA1( K || "A" || H ) sc-encryption-iv = SHA1( K || "B" || H ) cs-encryption-key-1 = SHA1( K || "C" || H ) cs-encryption-key-2 = SHA1( K || cs-encryption-key-1 ) cs-encryption-key = cs-encryption-key-1 || cs-encryption-key-2 sc-encryption-key-1 = SHA1( K || "D" || H ) sc-encryption-key-2 = SHA1( K || sc-encryption-key-1 ) sc-encryption-key = sc-encryption-key-1 || sc-encryption-key-2 cs-integrity-key = SHA1( K || "E" || H ) sc-integrity-key = SHA1( K || "F" || H ) K is dh_k in mpint format (string) H is hash */ /* Since we won't support SASL security layers, we need to * compute the following only: * cs-encryption-iv * cs-encryption-key * cs-integrity-key */ buffer_clear(Buf_Space); buffer_put_bignum(Buf_Space, dh_K); buffer_put_octet(Buf_Space,'A'); buffer_append(Buf_Space, hash, 20); SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash); /* Use first 8 octets as iv */ memcpy(enc_iv, tmphash, 8); buffer_clear(Buf_Space); buffer_put_bignum(Buf_Space, dh_K); buffer_put_octet(Buf_Space,'E'); buffer_append(Buf_Space, hash, 20); SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), int_key); buffer_clear(Buf_Space); buffer_put_bignum(Buf_Space, dh_K); buffer_put_octet(Buf_Space,'C'); buffer_append(Buf_Space, hash, 20); SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash); buffer_clear(Buf_Space); buffer_put_bignum(Buf_Space, dh_K); buffer_append(Buf_Space, tmphash, 20); SHA1(buffer_ptr(Buf_Space), buffer_len(Buf_Space), tmphash+20); /* Use first 24 octets as key */ memcpy(enc_key, tmphash, 24); { BIGNUM *enc, *i, *iv; enc = BN_bin2bn(enc_key, 24, NULL); iv = BN_bin2bn(enc_iv, 8, NULL); i = BN_bin2bn(int_key, 20, NULL); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_PASSDS_ENC_KEY, BN_bn2hex(enc)); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_PASSDS_IV, BN_bn2hex(iv)); Display(LOG_LEVEL_3, ELDebug, TSP_AUTH_PASSDSS_STRING, GOGO_STR_PASSDS_INTEG_KEY, BN_bn2hex(i)); BN_free(enc); BN_free(i); BN_free(iv); } /* (J) Create a buffer beginning with a bit mask for the selected security layer (it MUST be one offered from server) followed by three octets representing the maximum cipher-text buffer size (at least 32) the client can accept in network byte order. This is followed by a string containing the passphrase. */ buffer_clear(Buf_Space); buffer_put_octet(Buf_Space, ssecmask); buffer_put_octet(Buf_Space, 0); buffer_put_octet(Buf_Space, 0); buffer_put_octet(Buf_Space, 0); /**< @bug must be at least 32 */ buffer_put_cstring(Buf_Space, conf->passwd); /* (K) Create a buffer containing items (1) through (7) immediately followed by the first four octets of (J). */ buffer_append(Buf_H, buffer_ptr(Buf_Space), 4); /* (L) Compute HMAC-SHA-1 with (K) as the data and the cs-integrity- key from step (I) as the key. This produces a 20 octet result. */ HMAC(EVP_sha1(), int_key, sizeof(int_key), buffer_ptr(Buf_H), buffer_len(Buf_H), hmac, (unsigned int*)&keysize); /* (M) Create a buffer containing (J) followed by (L) followed by an arbitrary number of zero octets as necessary to reach the block size of DES and conceal the passphrase length from an eavesdropper. */ buffer_append(Buf_Space, hmac, keysize); /* (N) Apply the triple-DES algorithm to (M) with the first 8 octets of cs-encryption-iv from step (I) as the initialization vector and the first 24 octets of cs-encryption-key as the key. */ /* Padding is automatically done. From OpenSSL EVP_EncryptInit(3): EVP_CIPHER_CTX_set_padding() enables or disables padding. By default encryption operations are padded using standard block padding and the padding is checked and removed when decrypting. */ /* Create BIO filter to encrypt using 3des + convert to base64. Result is written in memory BIO. */ /* Erase BIO and buffer memory */ BIO_reset(bio_rw); memset(BufferOut, 0, TSP_AUTH_PASSDSS_BUFFERSIZE); memset(BufferIn, 0, TSP_AUTH_PASSDSS_BUFFERSIZE); buflen = 0; /* Create cipher BIO */ cipher = BIO_new(BIO_f_cipher()); BIO_set_cipher(cipher, EVP_des_ede3_cbc(), enc_key, enc_iv, 1); /* Assemble filters as cipher->b64->bio_rw */ BIO_push(cipher, b64); BIO_push(b64, bio_rw); /* Write Buffer content into bio_rw */ BIO_write(cipher, buffer_ptr(Buf_Space), (int) buffer_len(Buf_Space)); BIO_flush(cipher); /* Get pointer to the result. */ buflen = BIO_get_mem_data(bio_rw, &BufferPtr); /* wipe encryption material */ memset(enc_key, 0, sizeof(enc_key)); memset(enc_iv, 0, sizeof(enc_iv)); /* Send data to server, save response in BufferIn */ if( (readlen = nt->netsendrecv(socket, BufferPtr, buflen, BufferIn, TSP_AUTH_PASSDSS_BUFFERSIZE)) == -1) { Display(LOG_LEVEL_1, ELError, TSP_AUTH_PASSDSS_STRING, STR_NET_FAIL_RW_SOCKET); status = make_status(CTX_TSPAUTHENTICATION, ERR_SOCKET_IO); goto error; } tsp_status = tspGetStatusCode(BufferIn); // Check if the reply status indicated a broker redirection. if( tspIsRedirectStatus(tsp_status) ) { if( tspHandleRedirect(BufferIn, conf, broker_list) == TSP_REDIRECT_OK ) { status = make_status(CTX_TSPAUTHENTICATION, EVNT_BROKER_REDIRECTION); } else { // Redirect error. status = make_status(CTX_TSPAUTHENTICATION, ERR_BROKER_REDIRECTION); } goto error; } // Check if authentication was successful. switch( tsp_status ) { case TSP_PROTOCOL_SUCCESS: break; case TSP_PROTOCOL_AUTH_FAILED: Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_AUTH_FAILED_USER, conf->userid); status = make_status(CTX_TSPAUTHENTICATION, ERR_AUTHENTICATION_FAILURE); goto error; default: Display(LOG_LEVEL_1, ELError, "AuthPASSDSS_3DES_1", STR_TSP_UNKNOWN_ERR_AUTH_FAILED, tspGetTspStatusStr(tsp_status)); status = make_status(CTX_TSPAUTHENTICATION, ERR_TSP_GENERIC_ERROR); goto error; } status = STATUS_SUCCESS_INIT; error: /* Free storage for DSA key */ if (dsa != NULL) DSA_free(dsa); /* Also frees BIGNUMs inside struct */ /* DSA signature */ if (sig != NULL) DSA_SIG_free(sig); /* Free Diffie Hellman variables */ if (dh != NULL) DH_free(dh); /* Also frees BIGNUMs inside struct */ if (server_pubkey != NULL) BN_free(server_pubkey); if (dh_K != NULL) BN_free(dh_K); /* Buffers */ if (Buf_Space->buf != NULL) buffer_free(Buf_Space); if (Buf_H->buf != NULL) buffer_free(Buf_H); /* malloc'ed space*/ if (BufferIn != NULL) pal_free(BufferIn); if (BufferOut != NULL) pal_free(BufferOut); /* BIOs */ if (cipher != NULL) BIO_vfree(cipher); if (b64 != NULL) BIO_vfree(b64); if (bio_rw != NULL) BIO_vfree(bio_rw); /* strings buffers */ if (s != NULL) pal_free(s); return status; }