/** * Perform User Authorization Request. * creates and send the user authorization query * @param msg - the SIP message * @param str1 - the realm * @param str2 - if to do capabilities * @returns true if OK, false if not */ int I_perform_user_authorization_request(struct sip_msg* msg, char* str1, char* str2) { str private_identity, public_identity, visited_network_id; int authorization_type = AVP_IMS_UAR_REGISTRATION; int expires = 3600; struct hdr_field *hdr; str realm; contact_t *c; int sos_reg = 0; contact_body_t *b = 0; str call_id; saved_uar_transaction_t* saved_t; tm_cell_t *t = 0; int intvalue_param; cfg_action_t* cfg_action; uar_param_t* ap = (uar_param_t*) str1; if (fixup_get_ivalue(msg, ap->ivalue, &intvalue_param) != 0) { LM_ERR("no int value param passed\n"); return CSCF_RETURN_ERROR; } cfg_action = ap->paction->next; realm = cscf_get_realm_from_ruri(msg); //check if we received what we should, we do this even though it should be done in cfg file - double checking! if (msg->first_line.type != SIP_REQUEST) { LM_ERR("ERR:I_UAR: The message is not a request\n"); return CSCF_RETURN_ERROR; } if (msg->first_line.u.request.method.len != 8 || memcmp(msg->first_line.u.request.method.s, "REGISTER", 8) != 0) { LM_ERR("ERR:I_UAR: The method is not a REGISTER\n"); return CSCF_RETURN_ERROR; } private_identity = cscf_get_private_identity(msg, realm); if (!private_identity.len) { LM_ERR("ERR:I_UAR: Private Identity not found, responding with 400\n"); cscf_reply_transactional(msg, 400, MSG_400_NO_PRIVATE); return CSCF_RETURN_BREAK; } public_identity = cscf_get_public_identity(msg); if (!public_identity.len) { LM_ERR("ERR:I_UAR: Public Identity not found, responding with 400\n"); cscf_reply_transactional(msg, 400, MSG_400_NO_PUBLIC); return CSCF_RETURN_BREAK; } b = cscf_parse_contacts(msg); if (!b || (!b->contacts && !b->star)) { LM_DBG("DBG:I_UAR: No contacts found\n"); return CSCF_RETURN_ERROR; } for (c = b->contacts; c; c = c->next) { sos_reg = cscf_get_sos_uri_param(c->uri); if (sos_reg == -1) { //error case LM_ERR("ERR:I_UAR: MSG_400_MALFORMED_CONTACT, responding with 400\n"); cscf_reply_transactional(msg, 400, MSG_400_MALFORMED_CONTACT); return CSCF_RETURN_BREAK; } else if (sos_reg == -2) { LM_ERR("ERR:I_UAR: MSG_500_SERVER_ERROR_OUT_OF_MEMORY, responding with 500\n"); cscf_reply_transactional(msg, 500, MSG_500_SERVER_ERROR_OUT_OF_MEMORY); return CSCF_RETURN_BREAK; } } visited_network_id = cscf_get_visited_network_id(msg, &hdr); if (!visited_network_id.len) { LM_ERR("ERR:I_UAR: Visited Network Identity not found, responding with 400\n"); cscf_reply_transactional(msg, 400, MSG_400_NO_VISITED); return CSCF_RETURN_BREAK; } if (atoi(str1)) authorization_type = AVP_IMS_UAR_REGISTRATION_AND_CAPABILITIES; else { expires = cscf_get_max_expires(msg, 0); if (expires == 0) authorization_type = AVP_IMS_UAR_DE_REGISTRATION; } LM_DBG("SENDING UAR: PI: [%.*s], PU: [%.*s], VNID: [%.*s]\n", private_identity.len, private_identity.s, public_identity.len, public_identity.s, visited_network_id.len, visited_network_id.s); //before we send lets suspend the transaction t = tmb.t_gett(); if (t == NULL || t == T_UNDEFINED) { if (tmb.t_newtran(msg) < 0) { LM_ERR("cannot create the transaction for UAR async\n"); cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR); return CSCF_RETURN_BREAK; } t = tmb.t_gett(); if (t == NULL || t == T_UNDEFINED) { LM_ERR("cannot lookup the transaction\n"); cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR); return CSCF_RETURN_BREAK; } } saved_t = shm_malloc(sizeof (saved_uar_transaction_t)); if (!saved_t) { LM_ERR("no more memory trying to save transaction state\n"); return CSCF_RETURN_ERROR; } memset(saved_t, 0, sizeof (saved_uar_transaction_t)); saved_t->act = cfg_action; call_id = cscf_get_call_id(msg, 0); saved_t->callid.s = (char*) shm_malloc(call_id.len + 1); if (!saved_t->callid.s) { LM_ERR("no more memory trying to save transaction state : callid\n"); shm_free(saved_t); return CSCF_RETURN_ERROR; } memset(saved_t->callid.s, 0, call_id.len + 1); memcpy(saved_t->callid.s, call_id.s, call_id.len); saved_t->callid.len = call_id.len; LM_DBG("Setting default AVP return code used for async callbacks to default as ERROR \n"); create_uaa_return_code(CSCF_RETURN_ERROR); LM_DBG("Suspending SIP TM transaction\n"); if (tmb.t_suspend(msg, &saved_t->tindex, &saved_t->tlabel) < 0) { LM_ERR("failed to suspend the TM processing\n"); free_saved_uar_transaction_data(saved_t); cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR); return CSCF_RETURN_BREAK; } if (cxdx_send_uar(msg, private_identity, public_identity, visited_network_id, authorization_type, sos_reg, saved_t) != 0) { LM_ERR("ERR:I_UAR: Error sending UAR or UAR time-out\n"); tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel); free_saved_uar_transaction_data(saved_t); cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR); return CSCF_RETURN_BREAK; } //we use async replies therefore we send break and not true when successful return CSCF_RETURN_BREAK; }
void async_cdp_uar_callback(int is_timeout, void *param, AAAMessage *uaa, long elapsed_msecs) { struct run_act_ctx ra_ctx; str server_name; int *m_capab = 0, m_capab_cnt = 0; int *o_capab = 0, o_capab_cnt = 0; str *p_server_names = 0; int p_server_names_cnt = 0; int rc = -1, experimental_rc = -1; saved_uar_transaction_t* data = (saved_uar_transaction_t*) param; struct cell *t = 0; int result = CSCF_RETURN_TRUE; scscf_entry *list = 0; if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) { LM_ERR("ERROR: t_continue: transaction not found\n"); //result = CSCF_RETURN_ERROR;//not needed we set by default to error! goto error; } if (is_timeout != 0) { LM_ERR("Error timeout when sending message via CDP\n"); update_stat(stat_uar_timeouts, 1); goto error; } //update stats on response time update_stat(uar_replies_received, 1); update_stat(uar_replies_response_time, elapsed_msecs); if (!uaa) { LM_ERR("Error sending message via CDP\n"); //result = CSCF_RETURN_ERROR;//not needed we set by default to error! goto error; } server_name = cxdx_get_server_name(uaa); if (!server_name.len) { cxdx_get_capabilities(uaa, &m_capab, &m_capab_cnt, &o_capab, &o_capab_cnt, &p_server_names, &p_server_names_cnt); } cxdx_get_result_code(uaa, &rc); cxdx_get_experimental_result_code(uaa, &experimental_rc); if (rc && !experimental_rc) { LM_ERR("No result code or experimental result code - responding 480\n"); cscf_reply_transactional_async(t, t->uas.request, 480, MSG_480_DIAMETER_MISSING_AVP); result = CSCF_RETURN_FALSE; goto done; } switch (rc) { case -1: switch (experimental_rc) { case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN: /* Check, if route is set: */ if (route_uar_user_unknown_no >= 0) { /* exec routing script */ init_run_actions_ctx(&ra_ctx); if (run_actions(&ra_ctx, main_rt.rlist[route_uar_user_unknown_no], t->uas.request) < 0) { LM_DBG("ims_icscf: error while trying script\n"); } } else { cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_USER_UNKNOWN); } LM_ERR("RC_IMS_DIAMETER_ERROR_USER_UNKNOWN\n"); result = CSCF_RETURN_FALSE; goto done; case RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH: LM_ERR("RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_IDENTITIES_DONT_MATCH); result = CSCF_RETURN_FALSE; goto done; case RC_IMS_DIAMETER_ERROR_ROAMING_NOT_ALLOWED: LM_ERR("RC_IMS_DIAMETER_ERROR_ROAMING_NOT_ALLOWED returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_ROAMING_NOT_ALLOWED); result = CSCF_RETURN_FALSE; goto done; case RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED: LM_ERR("RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_IDENTITY_NOT_REGISTERED); result = CSCF_RETURN_FALSE; goto done; case RC_IMS_DIAMETER_FIRST_REGISTRATION: goto success; case RC_IMS_DIAMETER_SUBSEQUENT_REGISTRATION: goto success; case RC_IMS_DIAMETER_SERVER_SELECTION: goto success; default: LM_ERR("MSG_403_UNKOWN_EXPERIMENTAL_RC returning 500\n"); cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_UNKOWN_EXPERIMENTAL_RC); result = CSCF_RETURN_FALSE; goto done; } break; case AAA_AUTHORIZATION_REJECTED: LM_ERR("AAA_AUTHORIZATION_REJECTED returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_AUTHORIZATION_REJECTED); result = CSCF_RETURN_FALSE; goto done; case AAA_UNABLE_TO_COMPLY: LM_ERR("AAA_UNABLE_TO_COMPLY returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_UNABLE_TO_COMPLY); result = CSCF_RETURN_FALSE; goto done; case AAA_SUCCESS: goto success; default: LM_ERR("MSG_403_UNKOWN_RC returning 403\n"); cscf_reply_transactional_async(t, t->uas.request, 403, MSG_403_UNKOWN_RC); result = CSCF_RETURN_FALSE; goto done; } success: LM_DBG("successful UAA response\n"); list = I_get_capab_ordered(server_name, m_capab, m_capab_cnt, o_capab, o_capab_cnt, p_server_names, p_server_names_cnt, 0); if (!list) { LM_ERR("Empty capability list returning 600\n"); cscf_reply_transactional_async(t, t->uas.request, 600, MSG_600_EMPTY_LIST); result = CSCF_RETURN_FALSE; goto done; } if (!data->callid.len || !add_scscf_list(data->callid, list)) { LM_ERR("Error saving capability list 500\n"); cscf_reply_transactional_async(t, t->uas.request, 500, MSG_500_ERROR_SAVING_LIST); result = CSCF_RETURN_FALSE; goto done; } result = CSCF_RETURN_TRUE; done: //free capabilities if they exist if (m_capab) shm_free(m_capab); if (o_capab) shm_free(o_capab); if (p_server_names) shm_free(p_server_names); LM_DBG("DBG:UAR Async CDP callback: ... Done resuming transaction\n"); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to); set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from); set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to); create_uaa_return_code(result); if (t)tmb.unref_cell(t); //free memory if (uaa) cdpb.AAAFreeMessage(&uaa); tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_uar_transaction_data(data); return; error: if (t)tmb.unref_cell(t); //free memory if (uaa) cdpb.AAAFreeMessage(&uaa); tmb.t_continue(data->tindex, data->tlabel, data->act); free_saved_uar_transaction_data(data); }