/* * Send Radius request to verify source. */ int verify_source(struct sip_msg* _msg, char* s1, char* s2) { aaa_message *send = NULL, *received = NULL; struct hdr_field *hf; uint32_t service; /* Add Request-URI host A_USER_NAME and user as A_SIP_URI_USER */ if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("error while parsing Request-URI\n"); return -1; } if ((send = proto.create_aaa_message(conn, AAA_AUTH)) == NULL) { LM_ERR("failed to create new aaa message for auth\n"); return -1; } if (proto.avp_add(conn, send, &attrs[A_USER_NAME], _msg->parsed_uri.host.s, _msg->parsed_uri.host.len, 0)) { LM_ERR("error adding PW_USER_NAME\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_URI_USER], _msg->parsed_uri.user.s, _msg->parsed_uri.user.len, 0)) { LM_ERR("error adding PW_SIP_URI_USER\n"); goto err; } /* Add From Tag */ if (parse_from_header(_msg) < 0) { LM_ERR("error while parsing From header field\n"); goto err; } if (_msg->from == NULL || get_from(_msg) == NULL || get_from(_msg)->tag_value.s == NULL || get_from(_msg)->tag_value.len <= 0) { LM_ERR("error while accessing From header tag\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_FROM_TAG], get_from(_msg)->tag_value.s, get_from(_msg)->tag_value.len, 0)) { LM_ERR("error adding PW_SIP_FROM_TAG\n"); goto err; } /* Add Call-Id */ if (parse_headers(_msg, HDR_CALLID_F, 0) == -1 || _msg->callid == NULL || _msg->callid->body.s == NULL || _msg->callid->body.len <= 0) { LM_ERR("error while accessing Call-Id\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_CALL_ID], _msg->callid->body.s, _msg->callid->body.len, 0)) { LM_ERR("error adding PW_SIP_CALL_ID\n"); goto err; } /* Add P-Request-Hash header body */ if (parse_headers(_msg, HDR_EOH_F, 0) < 0) { LM_ERR("cannot pase message!\n"); goto err; } hf = get_header_by_static_name( _msg, "P-Request-Hash"); if (!hf) { LM_ERR("no P-Request-Hash header field\n"); goto err; } if (hf->body.s == NULL || hf->body.len <= 0) { LM_ERR("error while accessing P-Request-Hash body\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_REQUEST_HASH], hf->body.s, hf->body.len, 0)) { LM_ERR("error adding PW_SIP_REQUEST_HASH\n"); goto err; } /* Add Service-Type */ service = vals[V_SIP_VERIFY_SOURCE].value; if (proto.avp_add(conn, send, &attrs[A_SERVICE_TYPE], &service, -1, 0)) { LM_ERR("error adding PW_SERVICE_TYPE\n"); goto err; } /* Send Request and generate AVPs of positive reply */ if (!proto.send_aaa_request(conn, send, &received)) { LM_DBG("success\n"); proto.destroy_aaa_message(conn, send); proto.destroy_aaa_message(conn, received); return 1; } LM_DBG("failure\n"); err: if (send) proto.destroy_aaa_message(conn, send); if (received) proto.destroy_aaa_message(conn, received); return -1; }
static int pv_auth_check(sip_msg_t *msg, str *srealm, str *spasswd, int vflags, int vchecks) { int ret; hdr_field_t *hdr; sip_uri_t *uri = NULL; sip_uri_t *turi = NULL; sip_uri_t *furi = NULL; str suser; if(msg->REQ_METHOD==METHOD_REGISTER) ret = pv_authenticate(msg, srealm, spasswd, vflags, HDR_AUTHORIZATION_T, &msg->first_line.u.request.method); else ret = pv_authenticate(msg, srealm, spasswd, vflags, HDR_PROXYAUTH_T, &msg->first_line.u.request.method); if(ret==AUTH_OK && (vchecks&AUTH_CHECK_ID_F)) { hdr = (msg->proxy_auth==0)?msg->authorization:msg->proxy_auth; suser = ((auth_body_t*)(hdr->parsed))->digest.username.user; if((furi=parse_from_uri(msg))==NULL) return AUTH_ERROR; if(msg->REQ_METHOD==METHOD_REGISTER || msg->REQ_METHOD==METHOD_PUBLISH) { if((turi=parse_to_uri(msg))==NULL) return AUTH_ERROR; uri = turi; } else { uri = furi; } if(suser.len!=uri->user.len || strncmp(suser.s, uri->user.s, suser.len)!=0) return AUTH_USER_MISMATCH; if(msg->REQ_METHOD==METHOD_REGISTER || msg->REQ_METHOD==METHOD_PUBLISH) { /* check from==to */ if(furi->user.len!=turi->user.len || strncmp(furi->user.s, turi->user.s, furi->user.len)!=0) return AUTH_USER_MISMATCH; if(auth_use_domain!=0 && (furi->host.len!=turi->host.len || strncmp(furi->host.s, turi->host.s, furi->host.len)!=0)) return AUTH_USER_MISMATCH; /* check r-uri==from for publish */ if(msg->REQ_METHOD==METHOD_PUBLISH) { if(parse_sip_msg_uri(msg)<0) return AUTH_ERROR; uri = &msg->parsed_uri; if(furi->user.len!=uri->user.len || strncmp(furi->user.s, uri->user.s, furi->user.len)!=0) return AUTH_USER_MISMATCH; if(auth_use_domain!=0 && (furi->host.len!=uri->host.len || strncmp(furi->host.s, uri->host.s, furi->host.len)!=0)) return AUTH_USER_MISMATCH; } } return AUTH_OK; } return ret; }
/* * Do loose routing as defined in RFC3261 */ int loose_route(struct sip_msg* _m, char* _s1, char* _s2) { int ret; removed_routes = 0; routing_type = 0; if (find_first_route(_m) != 0) { LM_DBG("There is no Route HF\n"); return -1; } if (parse_sip_msg_uri(_m)<0) { LM_ERR("failed to parse Request URI\n"); return -1; } ret = is_preloaded(_m); if (ret < 0) { return -1; } else if (ret == 1) { return after_loose(_m, 1); } else { #ifdef ENABLE_USER_CHECK if (is_myself(&_m->parsed_uri.user, &_m->parsed_uri.host, _m->parsed_uri.port_no)) { #else if (is_myself(&_m->parsed_uri.host, _m->parsed_uri.port_no)) { #endif return after_strict(_m); } else { return after_loose(_m, 0); } } } int get_route_params(struct sip_msg *msg, str *val) { if(msg==NULL) return -1; /* check if the hooked params belong to the same message */ if (routed_msg_id != msg->id) return -1; val->s = routed_params.s; val->len = routed_params.len; return 0; } int check_route_param(struct sip_msg * msg, regex_t* re) { regmatch_t pmatch; char bk; str params; /* check if the hooked params belong to the same message */ if (routed_msg_id != msg->id) return -1; /* check if params are present */ if ( !routed_params.s || !routed_params.len ) return -1; /* include also the first ';' */ for( params=routed_params ; params.s[0]!=';' ; params.s--,params.len++ ); /* do the well-known trick to convert to null terminted */ bk = params.s[params.len]; params.s[params.len] = 0; LM_DBG("params are <%s>\n", params.s); if (regexec( re, params.s, 1, &pmatch, 0)!=0) { params.s[params.len] = bk; return -1; } else { params.s[params.len] = bk; return 0; } }
int rls_handle_subscribe(struct sip_msg* msg, char* s1, char* s2) { struct to_body *pto, *pfrom = NULL; subs_t subs; pres_ev_t* event= NULL; str* contact= NULL; xmlDocPtr doc= NULL; xmlNodePtr service_node= NULL; unsigned int hash_code= 0; event_t* parsed_event; param_t* ev_param= NULL; int init_req; int reply_code; str reply_str; /*** filter: 'For me or for presence server?' */ reply_code = 400; reply_str = pu_400_rpl; memset(&subs, 0, sizeof(subs_t)); if ( parse_headers(msg,HDR_EOH_F, 0)==-1 ) { LM_ERR("parsing headers\n"); goto error; } /* check for Support: eventlist header */ if(!msg->supported) { LM_DBG("no supported header found\n"); return to_presence_code; } if(parse_supported(msg) < 0) { LM_ERR("failed to parse supported headers\n"); reply_code = 500; reply_str = pu_500_rpl; goto error; } if(!(get_supported(msg) & F_SUPPORTED_EVENTLIST)) { LM_DBG("No 'Support: eventlist' header found\n"); return to_presence_code; } /* inspecting the Event header field */ if(msg->event && msg->event->body.len > 0) { if (!msg->event->parsed && (parse_event(msg->event) < 0)) { LM_ERR("cannot parse Event header\n"); reply_code = 500; reply_str = pu_500_rpl; goto error; } if(! ( ((event_t*)msg->event->parsed)->parsed & rls_events) ) { return to_presence_code; } } else { goto bad_event; } /* search event in the list */ parsed_event= (event_t*)msg->event->parsed; event= pres_search_event(parsed_event); if(event== NULL) { goto bad_event; } subs.event= event; /* extract the id if any*/ ev_param= parsed_event->params; while(ev_param) { if(ev_param->name.len== 2 && strncasecmp(ev_param->name.s, "id", 2)== 0) { subs.event_id= ev_param->body; break; } ev_param= ev_param->next; } pto = get_to(msg); if (pto == NULL || pto->error != PARSE_OK) { LM_ERR("parsing 'To' header failed\n"); goto error; } if(parse_from_uri(msg)<0) { LM_ERR("failed to parse From header\n"); goto error; } pfrom = (struct to_body*)msg->from->parsed; if(pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0) { LM_ERR("no from tag value present\n"); goto error; } /* verify if the presentity URI is a resource list */ if(pto->tag_value.s== NULL || pto->tag_value.len==0) /* if an initial Subscribe */ { struct sip_uri fu = ((struct to_body*)msg->from->parsed)->parsed_uri; if( parse_sip_msg_uri(msg)< 0) { LM_ERR("parsing Request URI failed\n"); goto error; } /*verify if Request URI represents a list by asking xcap server*/ if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host, &subs.pres_uri)< 0) { LM_ERR("while constructing uri from user and domain\n"); reply_code = 500; reply_str = pu_500_rpl; goto error; } if( get_resource_list(&subs.pres_uri, fu.user, fu.host, &service_node, &doc) < 0) { LM_ERR("failed to get resource list document\n"); reply_code = 500; reply_str = pu_500_rpl; goto error; } if(doc== NULL|| service_node==NULL) { LM_DBG("list not found - search for uri = %.*s\n",subs.pres_uri.len, subs.pres_uri.s); pkg_free(subs.pres_uri.s); return to_presence_code; } } else /* if request inside a dialog */ { if( msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot parse callid header\n"); goto error; } /* search if a stored dialog */ hash_code= core_hash(&msg->callid->body, &pto->tag_value, hash_size); lock_get(&rls_table[hash_code].lock); if(pres_search_shtable(rls_table,msg->callid->body, pto->tag_value, pfrom->tag_value, hash_code)== NULL) { lock_release(&rls_table[hash_code].lock); /* reply with Call/Transaction Does Not Exist */ LM_DBG("No dialog match found\n"); return to_presence_code; } lock_release(&rls_table[hash_code].lock); } /* extract dialog information from message headers */ if(pres_extract_sdialog_info(&subs, msg, rls_max_expires, &init_req, server_address)< 0) { LM_ERR("bad Subscribe request\n"); goto error; } reply_code = 500; reply_str = pu_500_rpl; if(init_req) /* if an initial subscribe */ { /** reply with 200 OK*/ if(reply_200(msg, &subs.local_contact, subs.expires, &subs.to_tag)< 0) goto error_free; hash_code= core_hash(&subs.callid, &subs.to_tag, hash_size); subs.local_cseq= 0; if(subs.expires!= 0) { subs.version= 1; if(pres_insert_shtable(rls_table, hash_code, &subs)< 0) { LM_ERR("while adding new subscription\n"); goto error_free; } } } else { if(update_rlsubs(&subs, hash_code, &reply_code, &reply_str) < 0) { LM_ERR("while updating resource list subscription\n"); goto error; } if(get_resource_list(&subs.pres_uri, subs.from_user, subs.from_domain, &service_node, &doc)< 0) { LM_ERR("when getting resource list\n"); goto error; } if(doc== NULL || service_node== NULL) { LM_DBG("list not found( in-dialog request)- search for uri = %.*s\n", subs.pres_uri.len, subs.pres_uri.s); reply_code = 404; reply_str = pu_404_rpl; goto error; } /** reply with 200 OK*/ if(reply_200(msg, &subs.local_contact, subs.expires, 0)< 0) goto error_free; } /*** send Subscribe requests for all in the list */ /* call sending Notify with full state */ if(send_full_notify(&subs, service_node, subs.version, &subs.pres_uri,hash_code)< 0) { LM_ERR("while sending full state Notify\n"); goto error_free; } if(resource_subscriptions(&subs, service_node)< 0) { LM_ERR("while sending Subscribe requests to resources in a list\n"); goto error_free; } if(contact) { if(contact->s) pkg_free(contact->s); pkg_free(contact); } pkg_free(subs.pres_uri.s); if(subs.record_route.s) pkg_free(subs.record_route.s); xmlFreeDoc(doc); return 1; bad_event: if(reply_489(msg)< 0) LM_ERR("failed to send 489 reply\n"); goto error_free; error: if (rls_sigb.reply(msg, reply_code, &reply_str, 0) == -1) { LM_ERR("failed to send 400 reply\n"); return -1; } error_free: if(contact) { if(contact->s) pkg_free(contact->s); pkg_free(contact); } if(subs.pres_uri.s) pkg_free(subs.pres_uri.s); if(subs.record_route.s) pkg_free(subs.record_route.s); if(doc) xmlFreeDoc(doc); return -1; }
int auth_check(sip_msg_t *_m, str *srealm, str *stable, int iflags) { int ret; hdr_field_t *hdr; sip_uri_t *uri = NULL; sip_uri_t *turi = NULL; sip_uri_t *furi = NULL; str suser; if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL)) { return AUTH_OK; } if (srealm->len<=0) { LM_ERR("invalid realm parameter - empty value\n"); return AUTH_ERROR; } if (stable->len==0) { LM_ERR("invalid table parameter - empty value\n"); return AUTH_ERROR; } LM_DBG("realm [%.*s] table [%.*s] flags [%d]\n", srealm->len, srealm->s, stable->len, stable->s, iflags); hdr = NULL; if(_m->REQ_METHOD==METHOD_REGISTER) ret = digest_authenticate_hdr(_m, srealm, stable, HDR_AUTHORIZATION_T, &_m->first_line.u.request.method, &hdr); else ret = digest_authenticate_hdr(_m, srealm, stable, HDR_PROXYAUTH_T, &_m->first_line.u.request.method, &hdr); if(ret==AUTH_OK && hdr!=NULL && (iflags&AUTH_CHECK_ID_F)) { suser = ((auth_body_t*)(hdr->parsed))->digest.username.user; if((furi=parse_from_uri(_m))==NULL) return AUTH_ERROR; if(_m->REQ_METHOD==METHOD_REGISTER || _m->REQ_METHOD==METHOD_PUBLISH) { if((turi=parse_to_uri(_m))==NULL) return AUTH_ERROR; uri = turi; } else { uri = furi; } if(!((iflags&AUTH_CHECK_SKIPFWD_F) && (_m->REQ_METHOD==METHOD_INVITE || _m->REQ_METHOD==METHOD_BYE || _m->REQ_METHOD==METHOD_PRACK || _m->REQ_METHOD==METHOD_UPDATE || _m->REQ_METHOD==METHOD_MESSAGE))) { if(suser.len!=uri->user.len || strncmp(suser.s, uri->user.s, suser.len)!=0) { LM_DBG("authentication username mismatch with from/to username\n"); return AUTH_USER_MISMATCH; } } if(_m->REQ_METHOD==METHOD_REGISTER || _m->REQ_METHOD==METHOD_PUBLISH) { /* check from==to */ if(furi->user.len!=turi->user.len || strncmp(furi->user.s, turi->user.s, furi->user.len)!=0) { LM_DBG("from username mismatch with to username\n"); return AUTH_USER_MISMATCH; } if(use_domain!=0 && (furi->host.len!=turi->host.len || strncmp(furi->host.s, turi->host.s, furi->host.len)!=0)) { LM_DBG("from domain mismatch with to domain\n"); return AUTH_USER_MISMATCH; } /* check r-uri==from for publish */ if(_m->REQ_METHOD==METHOD_PUBLISH) { if(parse_sip_msg_uri(_m)<0) return AUTH_ERROR; uri = &_m->parsed_uri; if(furi->user.len!=uri->user.len || strncmp(furi->user.s, uri->user.s, furi->user.len)!=0) { LM_DBG("from username mismatch with r-uri username\n"); return AUTH_USER_MISMATCH; } if(use_domain!=0 && (furi->host.len!=uri->host.len || strncmp(furi->host.s, uri->host.s, furi->host.len)!=0)) { LM_DBG("from domain mismatch with r-uri domain\n"); return AUTH_USER_MISMATCH; } } } return AUTH_OK; } return ret; }
int enum_pv_query_3(struct sip_msg* _msg, char* _sp, char* _suffix, char* _service) { char *user_s; int user_len, i, j, first; char name[MAX_DOMAIN_SIZE]; char uri[MAX_URI_SIZE]; char new_uri[MAX_URI_SIZE]; unsigned int priority, curr_prio; qvalue_t q; char tostring[17]; struct rdata* head; struct rdata* l; struct naptr_rdata* naptr; str pattern, replacement, result, new_result; str *suffix, *service; char string[17]; pv_spec_t *sp; pv_value_t pv_val; sp = (pv_spec_t *)_sp; suffix = (str*)_suffix; service = (str*)_service; /* * Get R-URI user to tostring */ if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("R-URI parsing failed\n"); return -1; } user_s = _msg->parsed_uri.user.s; user_len = _msg->parsed_uri.user.len; memcpy(&(tostring[0]), user_s, user_len); tostring[user_len] = (char)0; /* * Get E.164 number from pseudo variable */ if (sp && (pv_get_spec_value(_msg, sp, &pv_val) == 0)) { if (pv_val.flags & PV_VAL_STR) { if (pv_val.rs.len == 0 || pv_val.rs.s == NULL) { LM_DBG("Missing E.164 number\n"); return -1; } } else { LM_DBG("Pseudo variable value is not string\n"); return -1; } } else { LM_DBG("Cannot get pseudo variable value\n"); return -1; } if (is_e164(&(pv_val.rs)) == -1) { LM_ERR("pseudo variable does not contain an E164 number\n"); return -1; } user_s = pv_val.rs.s; user_len = pv_val.rs.len; memcpy(&(string[0]), user_s, user_len); string[user_len] = (char)0; j = 0; for (i = user_len - 1; i > 0; i--) { name[j] = user_s[i]; name[j + 1] = '.'; j = j + 2; } memcpy(name + j, suffix->s, suffix->len + 1); head = get_record(name, T_NAPTR); if (head == 0) { LM_DBG("No NAPTR record found for %s.\n", name); return -1; } naptr_sort(&head); q = MAX_Q - 10; curr_prio = 0; first = 1; for (l = head; l; l = l->next) { if (l->type != T_NAPTR) continue; /*should never happen*/ naptr = (struct naptr_rdata*)l->rdata; if (naptr == 0) { LM_ERR("Null rdata in DNS response\n"); continue; } LM_DBG("ENUM query on %s: order %u, pref %u, flen %u, flags " "'%.*s', slen %u, services '%.*s', rlen %u, " "regexp '%.*s'\n", name, naptr->order, naptr->pref, naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags), naptr->services_len, (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len, (int)(naptr->regexp_len), ZSW(naptr->regexp)); if (sip_match(naptr, service) == 0) continue; if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len, &pattern, &replacement) < 0) { LM_ERR("Parsing of NAPTR regexp failed\n"); continue; } result.s = &(uri[0]); result.len = MAX_URI_SIZE; /* Avoid making copies of pattern and replacement */ pattern.s[pattern.len] = (char)0; replacement.s[replacement.len] = (char)0; if (reg_replace(pattern.s, replacement.s, &(tostring[0]), &result) < 0) { pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; LM_ERR("Regexp replace failed\n"); continue; } LM_DBG("Resulted in replacement: '%.*s'\n", result.len, ZSW(result.s)); pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; if (param.len > 0) { if (result.len + param.len > MAX_URI_SIZE - 1) { LM_ERR("URI is too long\n"); continue; } new_result.s = &(new_uri[0]); new_result.len = MAX_URI_SIZE; if (add_uri_param(&result, ¶m, &new_result) == 0) { LM_ERR("Parsing of URI <%.*s> failed\n", result.len, result.s); continue; } if (new_result.len > 0) { result = new_result; } } if (first) { if (set_ruri(_msg, &result) == -1) { goto done; } set_ruri_q(_msg, q); first = 0; curr_prio = ((naptr->order) << 16) + naptr->pref; } else { priority = ((naptr->order) << 16) + naptr->pref; if (priority > curr_prio) { q = q - 10; curr_prio = priority; } if (append_branch(_msg, &result, 0, 0, q, 0, 0) == -1) { goto done; } } } done: free_rdata_list(head); return first ? -1 : 1; }
/* * Do loose routing as defined in RFC3261 */ int loose_route(struct sip_msg* _m) { int ret; ctx_routing_set(0); if (find_first_route(_m) != 0) { LM_DBG("There is no Route HF\n"); return -1; } if (parse_sip_msg_uri(_m)<0) { LM_ERR("failed to parse Request URI\n"); return -1; } ret = is_preloaded(_m); if (ret < 0) { return -1; } else if (ret == 1) { return after_loose(_m, 1); } else { #ifdef ENABLE_USER_CHECK if (is_myself(&_m->parsed_uri.user, &_m->parsed_uri.host, _m->parsed_uri.port_no) && !(_m->parsed_uri.gr.s && _m->parsed_uri.gr.len)) { #else if (is_myself(&_m->parsed_uri.host, _m->parsed_uri.port_no) && !(_m->parsed_uri.gr.s && _m->parsed_uri.gr.len)) { #endif return after_strict(_m); } else { return after_loose(_m, 0); } } } int get_route_params(struct sip_msg *msg, str *val) { if(msg==NULL) return -1; /* check if params are present */ if ( (val=ctx_rrparam_get())==NULL ) return -1; return 0; } int check_route_param(struct sip_msg * msg, regex_t* re) { regmatch_t pmatch; char bk; str params; str *rparams; /* check if params are present */ if ( (rparams=ctx_rrparam_get())==NULL || rparams->len==0) return -1; /* include also the first ';' */ for( params=*rparams ; params.s[0]!=';' ; params.s--,params.len++ ); /* do the well-known trick to convert to null terminted */ bk = params.s[params.len]; params.s[params.len] = 0; LM_DBG("params are <%s>\n", params.s); if (regexec( re, params.s, 1, &pmatch, 0)!=0) { params.s[params.len] = bk; return -1; } else { params.s[params.len] = bk; return 0; } }
/* * Find if Request URI has a given parameter with matching value */ int uri_param_2(struct sip_msg* _msg, char* _param, char* _value) { str param, value, t; param_hooks_t hooks; param_t* params; if (get_str_fparam(¶m, _msg, (fparam_t *)_param) < 0) { ERR("is_user: failed to recover 1st parameter.\n"); return -1; } if (_value) { if (get_str_fparam(&value, _msg, (fparam_t *)_value) < 0) { ERR("is_user: failed to recover 1st parameter.\n"); return -1; } } else { value.s = 0; } if (parse_sip_msg_uri(_msg) < 0) { LOG(L_ERR, "uri_param(): ruri parsing failed\n"); return -1; } t = _msg->parsed_uri.params; if (parse_params(&t, CLASS_ANY, &hooks, ¶ms) < 0) { LOG(L_ERR, "uri_param(): ruri parameter parsing failed\n"); return -1; } while (params) { if ((params->name.len == param.len) && (strncmp(params->name.s, param.s, param.len) == 0)) { if (value.s) { if ((value.len == params->body.len) && strncmp(value.s, params->body.s, value.len) == 0) { goto ok; } else { goto nok; } } else { if (params->body.len > 0) { goto nok; } else { goto ok; } } } else { params = params->next; } } nok: free_params(params); return -1; ok: free_params(params); return 1; }
/* * Adds a new parameter to Request URI */ int add_uri_param(struct sip_msg* _msg, char* _param, char* _s2) { str param, *cur_uri, new_uri; struct sip_uri *parsed_uri; char *at; if (get_str_fparam(¶m, _msg, (fparam_t *)_param) < 0) { ERR("add_uri_param: failed to recover parameter.\n"); return -1; } if (param.len == 0) { return 1; } if (parse_sip_msg_uri(_msg) < 0) { LOG(L_ERR, "add_uri_param(): ruri parsing failed\n"); return -1; } parsed_uri = &(_msg->parsed_uri); /* if current ruri has no headers, pad param at the end */ if (parsed_uri->headers.len == 0) { cur_uri = GET_RURI(_msg); new_uri.len = cur_uri->len + param.len + 1; if (new_uri.len > MAX_URI_SIZE) { LOG(L_ERR, "add_uri_param(): new ruri too long\n"); return -1; } new_uri.s = pkg_malloc(new_uri.len); if (new_uri.s == 0) { LOG(L_ERR, "add_uri_param(): Memory allocation failure\n"); return -1; } memcpy(new_uri.s, cur_uri->s, cur_uri->len); *(new_uri.s + cur_uri->len) = ';'; memcpy(new_uri.s + cur_uri->len + 1, param.s, param.len); if (rewrite_uri(_msg, &new_uri ) == 1) { goto ok; } else { goto nok; } } /* otherwise take the long path */ new_uri.len = 4 + (parsed_uri->user.len ? parsed_uri->user.len + 1 : 0) + (parsed_uri->passwd.len ? parsed_uri->passwd.len + 1 : 0) + parsed_uri->host.len + (parsed_uri->port.len ? parsed_uri->port.len + 1 : 0) + parsed_uri->params.len + param.len + 1 + parsed_uri->headers.len + 1; if (new_uri.len > MAX_URI_SIZE) { LOG(L_ERR, "add_uri_param(): new ruri too long\n"); return -1; } new_uri.s = pkg_malloc(new_uri.len); if (new_uri.s == 0) { LOG(L_ERR, "add_uri_param(): Memory allocation failure\n"); return -1; } at = new_uri.s; memcpy(at, "sip:", 4); at = at + 4; if (parsed_uri->user.len) { memcpy(at, parsed_uri->user.s, parsed_uri->user.len); if (parsed_uri->passwd.len) { *at = ':'; at = at + 1; memcpy(at, parsed_uri->passwd.s, parsed_uri->passwd.len); at = at + parsed_uri->passwd.len; }; *at = '@'; at = at + 1; } memcpy(at, parsed_uri->host.s, parsed_uri->host.len); at = at + parsed_uri->host.len; if (parsed_uri->port.len) { *at = ':'; at = at + 1; memcpy(at, parsed_uri->port.s, parsed_uri->port.len); at = at + parsed_uri->port.len; } memcpy(at, parsed_uri->params.s, parsed_uri->params.len); at = at + parsed_uri->params.len; *at = ';'; at = at + 1; memcpy(at, param.s, param.len); at = at + param.len; *at = '?'; at = at + 1; memcpy(at, parsed_uri->headers.s, parsed_uri->headers.len); if (rewrite_uri(_msg, &new_uri) == 1) { goto ok; } nok: pkg_free(new_uri.s); return -1; ok: pkg_free(new_uri.s); return 1; }
/* * Get number portability parameter from Request-Line * param msg SIP message * param rn Routing number * param rnbufsize Size of rn buffer * param cic Carrier identification code * param cicbufsize Size of cic buffer * param npdi NP database dip indicator * return 0 success, 1 not use NP or without NP parameters, -1 failure */ int ospGetNpParameters( struct sip_msg* msg, char* rn, int rnbufsize, char* cic, int cicbufsize, int* npdi) { str sv; param_hooks_t phooks; param_t* params = NULL; param_t* pit; int result = -1; if (((rn != NULL) && (rnbufsize > 0)) && ((cic != NULL) && (cicbufsize > 0)) && (npdi != NULL)) { rn[0] = '\0'; cic[0] = '\0'; *npdi = 0; if (_osp_use_np != 0) { if (parse_sip_msg_uri(msg) >= 0) { switch (msg->parsed_uri.type) { case TEL_URI_T: case TELS_URI_T: sv = msg->parsed_uri.params; break; case ERROR_URI_T: case SIP_URI_T: case SIPS_URI_T: default: sv = msg->parsed_uri.user; break; } parse_params(&sv, CLASS_ANY, &phooks, ¶ms); for (pit = params; pit; pit = pit->next) { if ((pit->name.len == OSP_RN_SIZE) && (strncasecmp(pit->name.s, OSP_RN_NAME, OSP_RN_SIZE) == 0) && (rn[0] == '\0')) { ospCopyStrToBuffer(&pit->body, rn, rnbufsize); } else if ((pit->name.len == OSP_CIC_SIZE) && (strncasecmp(pit->name.s, OSP_CIC_NAME, OSP_CIC_SIZE) == 0) && (cic[0] == '\0')) { ospCopyStrToBuffer(&pit->body, cic, cicbufsize); } else if ((pit->name.len == OSP_NPDI_SIZE) && (strncasecmp(pit->name.s, OSP_NPDI_NAME, OSP_NPDI_SIZE) == 0)) { *npdi = 1; } } if (params != NULL) { free_params(params); } if ((rn[0] != '\0') || (cic[0] != '\0') || (*npdi != 0)) { result = 0; } else { LM_DBG("without number portability parameters\n"); result = 1; } } else { LM_ERR("failed to parse Request-Line URI\n"); } } else { LM_DBG("do not use number portability\n"); result = 1; } } else { LM_ERR("bad parameters to parse number portability parameters\n"); } return result; }
/* * Get operator name from Request-Line * param msg SIP message * param type Operator name type * param name Operator name buffer * param namebufsize Size of name buffer * return 0 success, 1 not use NP or without operator name, -1 failure */ int ospGetOperatorName( struct sip_msg* msg, OSPE_OPERATOR_NAME type, char* name, int namebufsize) { str sv; param_hooks_t phooks; param_t* params = NULL; param_t* pit; int result = -1; if (((name != NULL) && (namebufsize > 0))) { name[0] = '\0'; if (_osp_use_np != 0) { if (parse_sip_msg_uri(msg) >= 0) { switch (msg->parsed_uri.type) { case TEL_URI_T: case TELS_URI_T: sv = msg->parsed_uri.params; break; case ERROR_URI_T: case SIP_URI_T: case SIPS_URI_T: default: sv = msg->parsed_uri.user; break; } parse_params(&sv, CLASS_ANY, &phooks, ¶ms); for (pit = params; pit; pit = pit->next) { switch (type) { case OSPC_OPNAME_SPID: if ((pit->name.len == OSP_SPID_SIZE) && (strncasecmp(pit->name.s, OSP_SPID_NAME, OSP_SPID_SIZE) == 0) && (name[0] == '\0')) { ospCopyStrToBuffer(&pit->body, name, namebufsize); } break; case OSPC_OPNAME_OCN: if ((pit->name.len == OSP_OCN_SIZE) && (strncasecmp(pit->name.s, OSP_OCN_NAME, OSP_OCN_SIZE) == 0) && (name[0] == '\0')) { ospCopyStrToBuffer(&pit->body, name, namebufsize); } break; case OSPC_OPNAME_SPN: if ((pit->name.len == OSP_SPN_SIZE) && (strncasecmp(pit->name.s, OSP_SPN_NAME, OSP_SPN_SIZE) == 0) && (name[0] == '\0')) { ospCopyStrToBuffer(&pit->body, name, namebufsize); } break; case OSPC_OPNAME_ALTSPN: if ((pit->name.len == OSP_ALTSPN_SIZE) && (strncasecmp(pit->name.s, OSP_ALTSPN_NAME, OSP_ALTSPN_SIZE) == 0) && (name[0] == '\0')) { ospCopyStrToBuffer(&pit->body, name, namebufsize); } break; case OSPC_OPNAME_MCC: if ((pit->name.len == OSP_MCC_SIZE) && (strncasecmp(pit->name.s, OSP_MCC_NAME, OSP_MCC_SIZE) == 0) && (name[0] == '\0')) { ospCopyStrToBuffer(&pit->body, name, namebufsize); } break; case OSPC_OPNAME_MNC: if ((pit->name.len == OSP_MNC_SIZE) && (strncasecmp(pit->name.s, OSP_MNC_NAME, OSP_MNC_SIZE) == 0) && (name[0] == '\0')) { ospCopyStrToBuffer(&pit->body, name, namebufsize); } break; default: break; } } if (params != NULL) { free_params(params); } if (name[0] != '\0') { result = 0; } else { LM_DBG("without operator name\n"); result = 1; } } else { LM_ERR("failed to parse Request-Line URI\n"); } } else { LM_DBG("do not use number portability\n"); result = 1; } } else { LM_ERR("bad parameters to parse operator name\n"); } return result; }
int perl_exec2(struct sip_msg* _msg, char* fnc, char* mystr) { int retval; SV *m; str reason; app_perl_reset_interpreter(); dSP; if (!perl_checkfnc(fnc)) { LM_ERR("unknown perl function called.\n"); reason.s = "Internal error"; reason.len = sizeof("Internal error")-1; if (slb.freply(_msg, 500, &reason) == -1) { LM_ERR("failed to send reply\n"); } return -1; } switch ((_msg->first_line).type) { case SIP_REQUEST: if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("failed to parse Request-URI\n"); reason.s = "Bad Request-URI"; reason.len = sizeof("Bad Request-URI")-1; if (slb.freply(_msg, 400, &reason) == -1) { LM_ERR("failed to send reply\n"); } return -1; } break; case SIP_REPLY: break; default: LM_ERR("invalid firstline"); return -1; } ENTER; /* everything created after here */ SAVETMPS; /* ...is a temporary variable. */ PUSHMARK(SP); /* remember the stack pointer */ m = sv_newmortal(); sv_setref_pv(m, "Kamailio::Message", (void *)_msg); SvREADONLY_on(SvRV(m)); XPUSHs(m); /* Our reference to the stack... */ if (mystr) XPUSHs(sv_2mortal(newSVpv(mystr, strlen(mystr)))); /* Our string to the stack... */ PUTBACK; /* make local stack pointer global */ call_pv(fnc, G_EVAL|G_SCALAR); /* call the function */ SPAGAIN; /* refresh stack pointer */ /* pop the return value from stack */ retval = POPi; PUTBACK; FREETMPS; /* free that return value */ LEAVE; /* ...and the XPUSHed "mortal" args.*/ return retval; }
int enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service) { char *user_s; int user_len, i, j, first; char name[MAX_DOMAIN_SIZE]; char uri[MAX_URI_SIZE]; char new_uri[MAX_URI_SIZE]; unsigned int priority, curr_prio; qvalue_t q; struct rdata* head; struct rdata* l; struct naptr_rdata* naptr; str pattern, replacement, result, new_result; char string[17]; str *suffix, *service; suffix = (str*)_suffix; service = (str*)_service; if (parse_sip_msg_uri(_msg) < 0) { LOG(L_ERR, "enum_query(): uri parsing failed\n"); return -1; } if (is_e164(&(_msg->parsed_uri.user)) == -1) { LOG(L_ERR, "enum_query(): uri user is not an E164 number\n"); return -1; } user_s = _msg->parsed_uri.user.s; user_len = _msg->parsed_uri.user.len; memcpy(&(string[0]), user_s, user_len); string[user_len] = (char)0; j = 0; for (i = user_len - 1; i > 0; i--) { name[j] = user_s[i]; name[j + 1] = '.'; j = j + 2; } memcpy(name + j, suffix->s, suffix->len + 1); head = get_record(name, T_NAPTR); if (head == 0) { DBG("enum_query(): No NAPTR record found for %s.\n", name); return -1; } naptr_sort(&head); q = MAX_Q - 10; curr_prio = 0; first = 1; for (l = head; l; l = l->next) { if (l->type != T_NAPTR) continue; /*should never happen*/ naptr = (struct naptr_rdata*)l->rdata; if (naptr == 0) { LOG(L_CRIT, "enum_query: BUG: null rdata\n"); continue; } DBG("enum_query(): order %u, pref %u, flen %u, flags '%.*s', slen %u, " "services '%.*s', rlen %u, regexp '%.*s'\n", naptr->order, naptr->pref, naptr->flags_len, (int)(naptr->flags_len), ZSW(naptr->flags), naptr->services_len, (int)(naptr->services_len), ZSW(naptr->services), naptr->regexp_len, (int)(naptr->regexp_len), ZSW(naptr->regexp)); if (sip_match(naptr, service) == 0) continue; if (parse_naptr_regexp(&(naptr->regexp[0]), naptr->regexp_len, &pattern, &replacement) < 0) { LOG(L_ERR, "enum_query(): parsing of NAPTR regexp failed\n"); continue; } result.s = &(uri[0]); result.len = MAX_URI_SIZE; /* Avoid making copies of pattern and replacement */ pattern.s[pattern.len] = (char)0; replacement.s[replacement.len] = (char)0; if (reg_replace(pattern.s, replacement.s, &(string[0]), &result) < 0) { pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; LOG(L_ERR, "enum_query(): regexp replace failed\n"); continue; } DBG("enum_query(): resulted in replacement: '%.*s'\n", result.len, ZSW(result.s)); pattern.s[pattern.len] = '!'; replacement.s[replacement.len] = '!'; if (param.len > 0) { if (result.len + param.len > MAX_URI_SIZE - 1) { LOG(L_ERR, "ERROR: enum_query(): URI is too long\n"); continue; } new_result.s = &(new_uri[0]); new_result.len = MAX_URI_SIZE; if (add_uri_param(&result, ¶m, &new_result) == 0) { LOG(L_ERR, "ERROR: enum_query(): Parsing of URI failed\n"); continue; } if (new_result.len > 0) { result = new_result; } } if (first) { if (rewrite_uri(_msg, &result) == -1) { goto done; } set_ruri_q(q); first = 0; curr_prio = ((naptr->order) << 16) + naptr->pref; } else { priority = ((naptr->order) << 16) + naptr->pref; if (priority > curr_prio) { q = q - 10; curr_prio = priority; } if (append_branch(_msg, &result, 0, q, 0, 0) == -1) { goto done; } } } done: free_rdata_list(head); return first ? -1 : 1; }
/* * Send Radius request to verify destination and generate AVPs from * reply items of positive response. */ int verify_destination(struct sip_msg* _msg, char* s1, char* s2) { aaa_message *send = NULL, *received = NULL; uint32_t service; /* Add Request-URI host A_USER_NAME and user as A_SIP_URI_USER */ if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("error while parsing Request-URI\n"); return -1; } if ((send = proto.create_aaa_message(conn, AAA_AUTH)) == NULL) { LM_ERR("failed to create new aaa message for auth\n"); return -1; } if (proto.avp_add(conn, send, &attrs[A_USER_NAME], _msg->parsed_uri.host.s, _msg->parsed_uri.host.len, 0)) { LM_ERR("error adding PW_USER_NAME\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_URI_USER], _msg->parsed_uri.user.s, _msg->parsed_uri.user.len, 0)) { LM_ERR("error adding PW_SIP_URI_USER\n"); goto err; } /* Add From Tag */ if (parse_from_header(_msg) < 0) { LM_ERR("error while parsing From header field\n"); goto err; } if ((_msg->from==NULL) || (get_from(_msg) == NULL) || (get_from(_msg)->tag_value.s == NULL) || (get_from(_msg)->tag_value.len <= 0)) { LM_ERR("error while accessing From header tag\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_FROM_TAG], get_from(_msg)->tag_value.s, get_from(_msg)->tag_value.len, 0)) { LM_ERR("error adding PW_SIP_FROM_TAG\n"); goto err; } /* Add Call-Id */ if ((parse_headers(_msg, HDR_CALLID_F, 0) == -1) || (_msg->callid == NULL) || (_msg->callid->body.s == NULL) || (_msg->callid->body.len <= 0)) { LM_ERR("error while accessing Call-Id\n"); goto err; } if (proto.avp_add(conn, send, &attrs[A_SIP_CALL_ID], _msg->callid->body.s, _msg->callid->body.len, 0)) { LM_ERR("error adding PW_SIP_CALL_ID\n"); goto err; } /* Add Service-Type */ service = vals[V_SIP_VERIFY_DESTINATION].value; if (proto.avp_add(conn, send, &attrs[A_SERVICE_TYPE], &service, -1, 0)) { LM_ERR("error adding PW_SERVICE_TYPE\n"); goto err; } /* Send Request and generate AVPs of positive reply */ if (!proto.send_aaa_request(conn, send, &received)) { LM_DBG("success\n"); proto.destroy_aaa_message(conn, send); proto.destroy_aaa_message(conn, received); return 1; } LM_DBG("failure\n"); err: if (send) proto.destroy_aaa_message(conn, send); if (received) proto.destroy_aaa_message(conn, received); return -1; }
static int load_avp_user(struct sip_msg* msg, str* prefix, load_avp_param_t type) { static char rad_msg[4096]; str user_domain, buffer; str* user, *domain, *uri; struct hdr_field* h; dig_cred_t* cred = 0; int_str name, val; unsigned short flags; VALUE_PAIR* send, *received, *vp; UINT4 service; struct sip_uri puri; send = received = 0; user_domain.s = 0; switch(type) { case LOAD_CALLER: /* Use From header field */ if (parse_from_header(msg) < 0) { LM_ERR("failed to parse From header field\n"); return -1; } uri = &get_from(msg)->uri; if (parse_uri(uri->s, uri->len, &puri) < 0) { LM_ERR("failed to parse From URI\n"); return -1; } user = &puri.user; domain = &puri.host; service = vals[V_SIP_CALLER_AVPS].v; break; case LOAD_CALLEE: /* Use the Request-URI */ if (parse_sip_msg_uri(msg) < 0) { LM_ERR("failed to parse Request-URI\n"); return -1; } if (msg->parsed_uri.user.len == 0) { LM_ERR("missing Request-URI user"); return -1; } user = &msg->parsed_uri.user; domain = &msg->parsed_uri.host; service = vals[V_SIP_CALLEE_AVPS].v; break; case LOAD_DIGEST: /* Use digest credentials */ get_authorized_cred(msg->proxy_auth, &h); if (!h) { LM_ERR("no authoried credentials\n"); return -1; } cred = &((auth_body_t*)(h->parsed))->digest; user = &cred->username.user; domain = &cred->realm; service = vals[V_SIP_CALLER_AVPS].v; break; default: LM_ERR("unknown user type\n"); return -1; } user_domain.len = user->len + 1 + domain->len; user_domain.s = (char*)pkg_malloc(user_domain.len); if (!user_domain.s) { LM_ERR("no pkg memory left\n"); return -1; } memcpy(user_domain.s, user->s, user->len); user_domain.s[user->len] = '@'; memcpy(user_domain.s + user->len + 1, domain->s, domain->len); if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, user_domain.s, user_domain.len, 0)) { LM_ERR("failed to add PW_USER_NAME\n"); goto error; } if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) { LM_ERR("failed to add PW_SERVICE_TYPE\n"); goto error; } if (rc_auth(rh, 0, send, &received, rad_msg) == OK_RC) { LM_DBG("rc_auth Success\n"); rc_avpair_free(send); pkg_free(user_domain.s); vp = received; for( ; (vp=rc_avpair_get(vp,attrs[A_SIP_AVP].v,0)) ; vp=vp->next) { flags = 0; if (extract_avp( vp, &flags, &name, &val)!=0 ) continue; /* append prefix only if AVP has name */ if (flags&AVP_NAME_STR) { buffer.len = prefix->len + name.s.len; buffer.s = (char*)pkg_malloc(buffer.len); if (!buffer.s) { LM_ERR("no pkg memory left\n"); return -1; } memcpy(buffer.s, prefix->s, prefix->len); memcpy(buffer.s + prefix->len, name.s.s, name.s.len); name.s = buffer; } else { buffer.s = 0; } if (add_avp( flags, name, val) < 0) { LM_ERR("unable to create a new AVP\n"); } else { LM_DBG("AVP '%.*s'/%d='%.*s'/%d has been added\n", (flags&AVP_NAME_STR)?name.s.len:4, (flags&AVP_NAME_STR)?name.s.s:"null", (flags&AVP_NAME_STR)?0:name.n, (flags&AVP_VAL_STR)?val.s.len:4, (flags&AVP_VAL_STR)?val.s.s:"null", (flags&AVP_VAL_STR)?0:val.n ); } if (buffer.s) pkg_free(buffer.s); } rc_avpair_free(received); return 1; } else { LM_ERR("rc_auth failed\n"); } error: if (send) rc_avpair_free(send); if (received) rc_avpair_free(received); if (user_domain.s) pkg_free(user_domain.s); return -1; }
static int imc_manager(struct sip_msg* msg, char *str1, char *str2) { imc_cmd_t cmd; str body; struct sip_uri from_uri, *pto_uri=NULL, *pfrom_uri=NULL; struct to_body *pfrom; if ( get_body( msg, &body)!=0 || body.len==0) { LM_DBG("empty body!\n"); goto error; } if(parse_sip_msg_uri(msg)<0) { LM_ERR("failed to parse r-uri\n"); goto error; } pto_uri=&msg->parsed_uri; if(parse_from_header(msg)<0) { LM_ERR("failed to parse From header\n"); goto error; } pfrom = (struct to_body*)msg->from->parsed; if(parse_uri(pfrom->uri.s, pfrom->uri.len, &from_uri)<0){ LM_ERR("failed to parse From URI\n"); goto error; } pfrom_uri=&from_uri; if(body.s[0]== imc_cmd_start_char) { LM_DBG("found command\n"); if(imc_parse_cmd(body.s, body.len, &cmd)<0) { LM_ERR("failed to parse imc cmd!\n"); goto error; } switch(cmd.type) { case IMC_CMDID_CREATE: if(imc_handle_create(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'create'\n"); goto error; } break; case IMC_CMDID_JOIN: if(imc_handle_join(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'join'\n"); goto error; } break; case IMC_CMDID_INVITE: if(imc_handle_invite(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'invite'\n"); goto error; } break; case IMC_CMDID_ACCEPT: if(imc_handle_accept(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'accept'\n"); goto error; } break; case IMC_CMDID_DENY: if(imc_handle_deny(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'deny'\n"); goto error; } break; case IMC_CMDID_REMOVE: if(imc_handle_remove(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'remove'\n"); goto error; } break; case IMC_CMDID_EXIT: if(imc_handle_exit(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'exit'\n"); goto error; } break; case IMC_CMDID_LIST: if(imc_handle_list(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'list'\n"); goto error; } break; case IMC_CMDID_DESTROY: if(imc_handle_destroy(msg, &cmd, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'destroy'\n"); goto error; } break; case IMC_CMDID_HELP: if(imc_handle_help(msg, &cmd, &pfrom->uri, (msg->new_uri.s)?&msg->new_uri:&msg->first_line.u.request.uri)<0) { LM_ERR("failed to handle 'help'\n"); goto error; } break; default: if(imc_handle_unknown(msg, &cmd, &pfrom->uri, (msg->new_uri.s)?&msg->new_uri:&msg->first_line.u.request.uri)<0) { LM_ERR("failed to handle 'unknown'\n"); goto error; } } goto done; } if(imc_handle_message(msg, &body, pfrom_uri, pto_uri)<0) { LM_ERR("failed to handle 'message'\n"); goto error; } done: return 1; error: return -1; }
int sd_lookup(struct sip_msg* _msg, char* _table, char* _owner) { str user_s, table_s, uri_s; int nr_keys; struct sip_uri *puri; struct sip_uri turi; db_key_t db_keys[4]; db_val_t db_vals[4]; db_key_t db_cols[1]; db1_res_t* db_res = NULL; if(_table==NULL || fixup_get_svalue(_msg, (gparam_p)_table, &table_s)!=0) { LM_ERR("invalid table parameter"); return -1; } /* init */ nr_keys = 0; db_cols[0]=&new_uri_column; if(_owner) { memset(&turi, 0, sizeof(struct sip_uri)); if(fixup_get_svalue(_msg, (gparam_p)_owner, &uri_s)!=0) { LM_ERR("invalid owner uri parameter"); return -1; } if(parse_uri(uri_s.s, uri_s.len, &turi)!=0) { LM_ERR("bad owner SIP address!\n"); goto err_server; } LM_DBG("using user id [%.*s]\n", uri_s.len, uri_s.s); puri = &turi; } else { /* take username@domain from From header */ if ( (puri = parse_from_uri(_msg ))==NULL ) { LM_ERR("failed to parse FROM header\n"); goto err_server; } } db_keys[nr_keys]=&user_column; db_vals[nr_keys].type = DB1_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = puri->user.s; db_vals[nr_keys].val.str_val.len = puri->user.len; nr_keys++; if(use_domain>=1) { db_keys[nr_keys]=&domain_column; db_vals[nr_keys].type = DB1_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = puri->host.s; db_vals[nr_keys].val.str_val.len = puri->host.len; nr_keys++; if (dstrip_s.s!=NULL && dstrip_s.len>0 && dstrip_s.len<puri->host.len && strncasecmp(puri->host.s,dstrip_s.s,dstrip_s.len)==0) { db_vals[nr_keys].val.str_val.s += dstrip_s.len; db_vals[nr_keys].val.str_val.len -= dstrip_s.len; } } /* take sd from r-uri */ if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("failed to parsing Request-URI\n"); goto err_server; } db_keys[nr_keys]=&sd_user_column; db_vals[nr_keys].type = DB1_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = _msg->parsed_uri.user.s; db_vals[nr_keys].val.str_val.len = _msg->parsed_uri.user.len; nr_keys++; if(use_domain>=2) { db_keys[nr_keys]=&sd_domain_column; db_vals[nr_keys].type = DB1_STR; db_vals[nr_keys].nul = 0; db_vals[nr_keys].val.str_val.s = _msg->parsed_uri.host.s; db_vals[nr_keys].val.str_val.len = _msg->parsed_uri.host.len; nr_keys++; if (dstrip_s.s!=NULL && dstrip_s.len>0 && dstrip_s.len<_msg->parsed_uri.host.len && strncasecmp(_msg->parsed_uri.host.s,dstrip_s.s,dstrip_s.len)==0) { db_vals[nr_keys].val.str_val.s += dstrip_s.len; db_vals[nr_keys].val.str_val.len -= dstrip_s.len; } } db_funcs.use_table(db_handle, &table_s); if(db_funcs.query(db_handle, db_keys, NULL, db_vals, db_cols, nr_keys /*no keys*/, 1 /*no cols*/, NULL, &db_res)!=0) { LM_ERR("failed to query database\n"); goto err_server; } if (RES_ROW_N(db_res)<=0 || RES_ROWS(db_res)[0].values[0].nul != 0) { LM_DBG("no sip addres found for R-URI\n"); if (db_res!=NULL && db_funcs.free_result(db_handle, db_res) < 0) LM_DBG("failed to free result of query\n"); return -1; } user_s.s = useruri_buf+4; switch(RES_ROWS(db_res)[0].values[0].type) { case DB1_STRING: strcpy(user_s.s, (char*)RES_ROWS(db_res)[0].values[0].val.string_val); user_s.len = strlen(user_s.s); break; case DB1_STR: strncpy(user_s.s, (char*)RES_ROWS(db_res)[0].values[0].val.str_val.s, RES_ROWS(db_res)[0].values[0].val.str_val.len); user_s.len = RES_ROWS(db_res)[0].values[0].val.str_val.len; user_s.s[user_s.len] = '\0'; break; case DB1_BLOB: strncpy(user_s.s, (char*)RES_ROWS(db_res)[0].values[0].val.blob_val.s, RES_ROWS(db_res)[0].values[0].val.blob_val.len); user_s.len = RES_ROWS(db_res)[0].values[0].val.blob_val.len; user_s.s[user_s.len] = '\0'; default: LM_ERR("unknown type of DB new_uri column\n"); if (db_res != NULL && db_funcs.free_result(db_handle, db_res) < 0) { LM_DBG("failed to free result of query\n"); } goto err_server; } /* check 'sip:' */ if(user_s.len<4 || strncmp(user_s.s, "sip:", 4)) { memcpy(useruri_buf, "sip:", 4); user_s.s -= 4; user_s.len += 4; } /** * Free the result because we don't need it anymore */ if (db_res!=NULL && db_funcs.free_result(db_handle, db_res) < 0) LM_DBG("failed to free result of query\n"); /* set the URI */ LM_DBG("URI of sd from R-URI [%s]\n", user_s.s); if(rewrite_ruri(_msg, user_s.s)<0) { LM_ERR("failed to replace the R-URI\n"); goto err_server; } return 1; err_server: return -1; }
static int opt_reply(struct sip_msg* _msg, char* _foo, char* _bar) { str rpl_hf; int offset = 0; /* check if it is called for an OPTIONS request */ if (_msg->REQ_METHOD!=METHOD_OPTIONS) { LM_ERR("called for non-OPTIONS request\n"); return -1; } if(_msg->parsed_uri_ok==0 && parse_sip_msg_uri(_msg)<0) { LM_ERR("ERROR while parsing the R-URI\n"); return -1; } /* FIXME: should we additionally check if ruri == server addresses ?! */ if (_msg->parsed_uri.user.len != 0) { LM_ERR("ruri contains username\n"); return -1; } /* calculate the length and allocated the mem */ rpl_hf.len = ACPT_STR_LEN + ACPT_ENC_STR_LEN + ACPT_LAN_STR_LEN + SUPT_STR_LEN + 4*HF_SEP_STR_LEN + acpt_s.len + acpt_enc_s.len + acpt_lan_s.len + supt_s.len; rpl_hf.s = (char*)pkg_malloc(rpl_hf.len); if (!rpl_hf.s) { LM_CRIT("out of pkg memory\n"); goto error; } /* create the header fields */ memcpy(rpl_hf.s, ACPT_STR, ACPT_STR_LEN); offset = ACPT_STR_LEN; memcpy(rpl_hf.s + offset, acpt_s.s, acpt_s.len); offset += acpt_s.len; memcpy(rpl_hf.s + offset, HF_SEP_STR, HF_SEP_STR_LEN); offset += HF_SEP_STR_LEN; memcpy(rpl_hf.s + offset, ACPT_ENC_STR, ACPT_ENC_STR_LEN); offset += ACPT_ENC_STR_LEN; memcpy(rpl_hf.s + offset, acpt_enc_s.s, acpt_enc_s.len); offset += acpt_enc_s.len; memcpy(rpl_hf.s + offset, HF_SEP_STR, HF_SEP_STR_LEN); offset += HF_SEP_STR_LEN; memcpy(rpl_hf.s + offset, ACPT_LAN_STR, ACPT_LAN_STR_LEN); offset += ACPT_LAN_STR_LEN; memcpy(rpl_hf.s + offset, acpt_lan_s.s, acpt_lan_s.len); offset += acpt_lan_s.len; memcpy(rpl_hf.s + offset, HF_SEP_STR, HF_SEP_STR_LEN); offset += HF_SEP_STR_LEN; memcpy(rpl_hf.s + offset, SUPT_STR, SUPT_STR_LEN); offset += SUPT_STR_LEN; memcpy(rpl_hf.s + offset, supt_s.s, supt_s.len); offset += supt_s.len; memcpy(rpl_hf.s + offset, HF_SEP_STR, HF_SEP_STR_LEN); #ifdef EXTRA_DEBUG offset += HF_SEP_STR_LEN; if (offset != rpl_hf.len) { LM_CRIT("headerlength (%i) != offset (%i)\n", rpl_hf.len, offset); abort(); } #endif if (add_lump_rpl( _msg, rpl_hf.s, rpl_hf.len, LUMP_RPL_HDR|LUMP_RPL_NODUP)!=0) { if (slb.reply(_msg, 200, &opt_200_rpl) == -1) { LM_ERR("failed to send 200 via send_reply\n"); return -1; } else return 0; } else { pkg_free(rpl_hf.s); LM_ERR("add_lump_rpl failed\n"); } error: if (slb.reply(_msg, 500, &opt_500_rpl) == -1) { LM_ERR("failed to send 500 via send_reply\n"); return -1; } else return 0; }
/* * See documentation in README file. */ int enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service) { char *user_s; int user_len, i, j; char name[MAX_DOMAIN_SIZE]; char string[17]; gparam_p gp = NULL; pv_value_t value; str __suffix = {0, 0}, __service = {0, 0}; /* Use the suffix module parameter */ if (_suffix == NULL) { __suffix.s = suffix.s; __suffix.len = suffix.len; } else { gp = (gparam_p) _suffix; if (gp->type == GPARAM_TYPE_PVS) { if (pv_get_spec_value(_msg, gp->v.pvs, &value) != 0 || value.flags & PV_VAL_NULL || value.flags & PV_VAL_EMPTY) { LM_ERR("No PV or NULL value specified for suffix\n"); return E_CFG; } if (value.flags & PV_VAL_STR) { __suffix.s = value.rs.s; __suffix.len = value.rs.len; } else { LM_ERR("Unsupported PV value type\n"); return E_CFG; } } else if (gp->type == GPARAM_TYPE_STR) { __suffix.s = gp->v.sval.s; __suffix.len = gp->v.sval.len; } } /* Use the internal service */ if (_service == NULL) { __service.s = service.s; __service.len = service.len; } else { gp = (gparam_p) _service; if (gp->type == GPARAM_TYPE_PVS) { if (pv_get_spec_value(_msg, gp->v.pvs, &value) != 0 || value.flags & PV_VAL_NULL || value.flags & PV_VAL_EMPTY) { LM_ERR("No PV or NULL value specified for suffix\n"); return E_CFG; } if (value.flags & PV_VAL_STR) { __service.s = value.rs.s; __service.len = value.rs.len; } else { LM_ERR("Unsupported PV value type\n"); return E_CFG; } } else if (gp->type == GPARAM_TYPE_STR) { __service.s = gp->v.sval.s; __service.len = gp->v.sval.len; } } if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("Parsing of R-URI failed\n"); return -1; } if (is_e164(&(_msg->parsed_uri.user)) == -1) { LM_ERR("R-URI user is not an E164 number\n"); return -1; } user_s = _msg->parsed_uri.user.s; user_len = _msg->parsed_uri.user.len; memcpy(&(string[0]), user_s, user_len); string[user_len] = (char)0; j = 0; for (i = user_len - 1; i > 0; i--) { name[j] = user_s[i]; name[j + 1] = '.'; j = j + 2; } memcpy(name + j, __suffix.s, __suffix.len + 1); return do_query(_msg, string, name, &__service); }
int corex_send(sip_msg_t *msg, gparam_t *pu, enum sip_protos proto) { str dest = {0}; int ret = 0; struct sip_uri next_hop, *u; struct dest_info dst; char *p; if (pu) { if (fixup_get_svalue(msg, pu, &dest)) { LM_ERR("cannot get the destination parameter\n"); return -1; } } init_dest_info(&dst); if (dest.len <= 0) { /*get next hop uri uri*/ if (msg->dst_uri.len) { ret = parse_uri(msg->dst_uri.s, msg->dst_uri.len, &next_hop); u = &next_hop; } else { ret = parse_sip_msg_uri(msg); u = &msg->parsed_uri; } if (ret<0) { LM_ERR("send() - bad_uri dropping packet\n"); ret=E_BUG; goto error; } } else { u = &next_hop; u->port_no = 5060; u->host = dest; p = memchr(dest.s, ':', dest.len); if (p) { u->host.len = p - dest.s; p++; u->port_no = str2s(p, dest.len - (p - dest.s), NULL); } } ret = sip_hostport2su(&dst.to, &u->host, u->port_no, &dst.proto); if(ret!=0) { LM_ERR("failed to resolve [%.*s]\n", u->host.len, ZSW(u->host.s)); ret=E_BUG; goto error; } dst.proto = proto; if (proto == PROTO_UDP) { dst.send_sock=get_send_socket(msg, &dst.to, PROTO_UDP); if (dst.send_sock!=0){ ret=udp_send(&dst, msg->buf, msg->len); }else{ ret=-1; } } #ifdef USE_TCP else{ /*tcp*/ dst.id=0; ret=tcp_send(&dst, 0, msg->buf, msg->len); } #endif if (ret>=0) ret=1; error: return ret; }
int get_username_domain(struct sip_msg *msg, group_check_p gcp, str *username, str *domain) { struct sip_uri puri; struct sip_uri *turi; struct hdr_field* h; struct auth_body* c = 0; /* Makes gcc happy */ pv_value_t value; turi = NULL; switch(gcp->id) { case 1: /* Request-URI */ if(parse_sip_msg_uri(msg)<0) { LM_ERR("failed to get Request-URI\n"); return -1; } turi = &msg->parsed_uri; break; case 2: /* To */ if((turi=parse_to_uri(msg))==NULL) { LM_ERR("failed to get To URI\n"); return -1; } break; case 3: /* From */ if((turi=parse_from_uri(msg))==NULL) { LM_ERR("failed to get From URI\n"); return -1; } break; case 4: /* Credentials */ get_authorized_cred( msg->authorization, &h); if (!h) { get_authorized_cred( msg->proxy_auth, &h); if (!h) { LM_ERR("no authorized credentials found " "(error in scripts)\n"); return -1; } } c = (auth_body_t*)(h->parsed); break; case 5: /* AVP spec */ if(pv_get_spec_value( msg, &gcp->sp, &value)!=0 || value.flags&PV_VAL_NULL || value.rs.len<=0) { LM_ERR("no AVP found (error in scripts)\n"); return -1; } if (parse_uri(value.rs.s, value.rs.len, &puri) < 0) { LM_ERR("failed to parse URI <%.*s>\n",value.rs.len, value.rs.s); return -1; } turi = &puri; break; } if (gcp->id != 4) { *username = turi->user; *domain = turi->host; } else { *username = c->digest.username.user; *domain = *(GET_REALM(&c->digest)); } return 0; }
/** * @brief change the r-uri domain based on source domain and prefix * * @param msg the sip message structure * @param sdomain the source domain * @param rmode the r-uri rewrite mode * @param fmode the source domain fallback mode * @return 1 if translation is done; -1 otherwise */ static int pd_translate(sip_msg_t *msg, str *sdomain, int rmode, int fmode) { str *d, p; str sdall={"*",1}; int plen; if(msg==NULL) { LM_ERR("received null msg\n"); return -1; } if(parse_sip_msg_uri(msg)<0) { LM_ERR("failed to parse the R-URI\n"); return -1; } /* if the user part begin with the prefix, extract the code*/ if (msg->parsed_uri.user.len<=0) { LM_DBG("user part of the message is empty\n"); return -1; } if(pdt_prefix.len>0) { if (msg->parsed_uri.user.len<=pdt_prefix.len) { LM_DBG("user part is less than prefix parameter\n"); return -1; } if(strncasecmp(pdt_prefix.s, msg->parsed_uri.user.s, pdt_prefix.len)!=0) { LM_DBG("prefix parameter did not matched\n"); return -1; } } p.s = msg->parsed_uri.user.s + pdt_prefix.len; p.len = msg->parsed_uri.user.len - pdt_prefix.len; again: lock_get( pdt_lock ); if (pdt_reload_flag) { lock_release( pdt_lock ); sleep_us(5); goto again; } pdt_tree_refcnt++; lock_release( pdt_lock ); if((d=pdt_get_domain(*_ptree, sdomain, &p, &plen))==NULL) { plen = 0; if((fmode==0) || (d=pdt_get_domain(*_ptree, &sdall, &p, &plen))==NULL) { LM_INFO("no prefix PDT prefix matched [%.*s]\n", p.len, p.s); goto error; } } /* update the new uri */ if(update_new_uri(msg, plen, d, rmode)<0) { LM_ERR("new_uri cannot be updated\n"); goto error; } lock_get( pdt_lock ); pdt_tree_refcnt--; lock_release( pdt_lock ); return 1; error: lock_get( pdt_lock ); pdt_tree_refcnt--; lock_release( pdt_lock ); return -1; }
/* * determines the permission of the call * return values: * -1: deny * 1: allow */ static int check_routing(struct sip_msg* msg, int idx) { struct hdr_field *from; int len, q; static char from_str[EXPRESSION_LENGTH+1]; static char ruri_str[EXPRESSION_LENGTH+1]; char* uri_str; str branch; int br_idx; /* turn off control, allow any routing */ if ((!allow[idx].rules) && (!deny[idx].rules)) { LM_DBG("no rules => allow any routing\n"); return 1; } /* looking for FROM HF */ if ((!msg->from) && (parse_headers(msg, HDR_FROM_F, 0) == -1)) { LM_ERR("failed to parse message\n"); return -1; } if (!msg->from) { LM_ERR("FROM header field not found\n"); return -1; } /* we must call parse_from_header explicitly */ if ((!(msg->from)->parsed) && (parse_from_header(msg) < 0)) { LM_ERR("failed to parse From body\n"); return -1; } from = msg->from; len = ((struct to_body*)from->parsed)->uri.len; if (len > EXPRESSION_LENGTH) { LM_ERR("From header field is too long: %d chars\n", len); return -1; } strncpy(from_str, ((struct to_body*)from->parsed)->uri.s, len); from_str[len] = '\0'; /* looking for request URI */ if (parse_sip_msg_uri(msg) < 0) { LM_ERR("uri parsing failed\n"); return -1; } len = msg->parsed_uri.user.len + msg->parsed_uri.host.len + 5; if (len > EXPRESSION_LENGTH) { LM_ERR("Request URI is too long: %d chars\n", len); return -1; } strcpy(ruri_str, "sip:"); memcpy(ruri_str + 4, msg->parsed_uri.user.s, msg->parsed_uri.user.len); ruri_str[msg->parsed_uri.user.len + 4] = '@'; memcpy(ruri_str + msg->parsed_uri.user.len + 5, msg->parsed_uri.host.s, msg->parsed_uri.host.len); ruri_str[len] = '\0'; LM_DBG("looking for From: %s Request-URI: %s\n", from_str, ruri_str); /* rule exists in allow file */ if (search_rule(allow[idx].rules, from_str, ruri_str)) { if (check_all_branches) goto check_branches; LM_DBG("allow rule found => routing is allowed\n"); return 1; } /* rule exists in deny file */ if (search_rule(deny[idx].rules, from_str, ruri_str)) { LM_DBG("deny rule found => routing is denied\n"); return -1; } if (!check_all_branches) { LM_DBG("neither allow nor deny rule found => routing is allowed\n"); return 1; } check_branches: for( br_idx=0 ; (branch.s=get_branch(br_idx,&branch.len,&q,0,0,0,0,0,0,0))!=0 ; br_idx++ ) { uri_str = get_plain_uri(&branch); if (!uri_str) { LM_ERR("failed to extract plain URI\n"); return -1; } LM_DBG("looking for From: %s Branch: %s\n", from_str, uri_str); if (search_rule(allow[idx].rules, from_str, uri_str)) { continue; } if (search_rule(deny[idx].rules, from_str, uri_str)) { LM_DBG("deny rule found for one of branches => routing" "is denied\n"); return -1; } } LM_DBG("check of branches passed => routing is allowed\n"); return 1; }
static int assemble_msg(struct sip_msg* msg, struct tw_info *twi) { static char id_buf[IDBUF_LEN]; static char route_buffer[ROUTE_BUFFER_MAX]; static char append_buf[APPEND_BUFFER_MAX]; static char cmd_buf[CMD_BUFFER_MAX]; static str empty_param = {".",1}; unsigned int hash_index, label; contact_body_t* cb=0; contact_t* c=0; name_addr_t na; rr_t* record_route; struct hdr_field* p_hdr; param_hooks_t hooks; int l; char* s, fproxy_lr; str route, next_hop, append, tmp_s, body, str_uri; if(msg->first_line.type != SIP_REQUEST){ LM_ERR("called for something else then a SIP request\n"); goto error; } /* parse all -- we will need every header field for a UAS */ if ( parse_headers(msg, HDR_EOH_F, 0)==-1) { LM_ERR("parse_headers failed\n"); goto error; } /* find index and hash; (the transaction can be safely used due * to refcounting till script completes) */ if( t_get_trans_ident(msg,&hash_index,&label) == -1 ) { LM_ERR("t_get_trans_ident failed\n"); goto error; } /* parse from header */ if (msg->from->parsed==0 && parse_from_header(msg)<0 ) { LM_ERR("failed to parse <From:> header\n"); goto error; } /* parse the RURI (doesn't make any malloc) */ msg->parsed_uri_ok = 0; /* force parsing */ if (parse_sip_msg_uri(msg)<0) { LM_ERR("uri has not been parsed\n"); goto error; } /* parse contact header */ str_uri.s = 0; str_uri.len = 0; if(msg->contact) { if (msg->contact->parsed==0 && parse_contact(msg->contact)<0) { LM_ERR("failed to parse <Contact:> header\n"); goto error; } cb = (contact_body_t*)msg->contact->parsed; if(cb && (c=cb->contacts)) { str_uri = c->uri; if (find_not_quoted(&str_uri,'<')) { parse_nameaddr(&str_uri,&na); str_uri = na.uri; } } } /* str_uri is taken from caller's contact or from header * for backwards compatibility with pre-3261 (from is already parsed)*/ if(!str_uri.len || !str_uri.s) str_uri = get_from(msg)->uri; /* parse Record-Route headers */ route.s = s = route_buffer; route.len = 0; fproxy_lr = 0; next_hop = empty_param; p_hdr = msg->record_route; if(p_hdr) { if (p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ) { LM_ERR("failed to parse 'Record-Route:' header\n"); goto error; } record_route = (rr_t*)p_hdr->parsed; } else { record_route = 0; } if( record_route ) { if ( (tmp_s.s=find_not_quoted(&record_route->nameaddr.uri,';'))!=0 && tmp_s.s+1!=record_route->nameaddr.uri.s+ record_route->nameaddr.uri.len) { /* Parse all parameters */ tmp_s.len = record_route->nameaddr.uri.len - (tmp_s.s- record_route->nameaddr.uri.s); if (parse_params( &tmp_s, CLASS_URI, &hooks, &record_route->params) < 0) { LM_ERR("failed to parse record route uri params\n"); goto error; } fproxy_lr = (hooks.uri.lr != 0); LM_DBG("record_route->nameaddr.uri: %.*s\n", record_route->nameaddr.uri.len,record_route->nameaddr.uri.s); if(fproxy_lr){ LM_DBG("first proxy has loose routing\n"); copy_route(s,route.len,record_route->nameaddr.uri.s, record_route->nameaddr.uri.len); } } for(p_hdr = p_hdr->next;p_hdr;p_hdr = p_hdr->next) { /* filter out non-RR hdr and empty hdrs */ if( (p_hdr->type!=HDR_RECORDROUTE_T) || p_hdr->body.len==0) continue; if(p_hdr->parsed==0 && parse_rr(p_hdr)!=0 ){ LM_ERR("failed to parse <Record-route:> header\n"); goto error; } for(record_route=p_hdr->parsed; record_route; record_route=record_route->next){ LM_DBG("record_route->nameaddr.uri: <%.*s>\n", record_route->nameaddr.uri.len, record_route->nameaddr.uri.s); copy_route(s,route.len,record_route->nameaddr.uri.s, record_route->nameaddr.uri.len); } } if(!fproxy_lr){ copy_route(s,route.len,str_uri.s,str_uri.len); str_uri = ((rr_t*)msg->record_route->parsed)->nameaddr.uri; } else { next_hop = ((rr_t*)msg->record_route->parsed)->nameaddr.uri; } } LM_DBG("calculated route: %.*s\n",route.len,route.len ? route.s : ""); LM_DBG("next r-uri: %.*s\n",str_uri.len,str_uri.len ? str_uri.s : ""); if ( REQ_LINE(msg).method_value==METHOD_INVITE || (twi->append && twi->append->add_body) ) { /* get body */ if( (body.s = get_body(msg)) == 0 ){ LM_ERR("get_body failed\n"); goto error; } body.len = msg->len - (body.s - msg->buf); } else { body = empty_param; } /* flags & additional headers */ append.s = s = append_buf; if (sizeof(flag_t)*2+12+1 >= APPEND_BUFFER_MAX) { LM_ERR("buffer overflow while copying flags\n"); goto error; } append_str(s,"P-MsgFlags: ",12); l = APPEND_BUFFER_MAX - (12+1); /* include trailing `\n'*/ if (int2reverse_hex(&s, &l, (int)msg->msg_flags) == -1) { LM_ERR("buffer overflow while copying optional header\n"); goto error; } append_chr(s,'\n'); if ( twi->append && ((s=append2buf( s, APPEND_BUFFER_MAX-(s-append.s), msg, twi->append->elems))==0) ) goto error; /* body separator */ append_chr(s,'.'); append.len = s-append.s; eol_line(1).s = s = cmd_buf; if(twi->action.len+12 >= CMD_BUFFER_MAX){ LM_ERR("buffer overflow while copying command name\n"); goto error; } append_str(s,"sip_request.",12); append_str(s,twi->action.s,twi->action.len); eol_line(1).len = s-eol_line(1).s; eol_line(2)=REQ_LINE(msg).method; /* method type */ eol_line(3)=msg->parsed_uri.user; /* user from r-uri */ eol_line(4)=msg->parsed_uri.host; /* domain */ eol_line(5)=msg->rcv.bind_address->address_str; /* dst ip */ eol_line(6)=msg->rcv.dst_port==SIP_PORT ? empty_param : msg->rcv.bind_address->port_no_str; /* port */ /* r_uri ('Contact:' for next requests) */ eol_line(7)=*GET_RURI(msg); /* r_uri for subsequent requests */ eol_line(8)=str_uri.len?str_uri:empty_param; eol_line(9)=get_from(msg)->body; /* from */ eol_line(10)=msg->to->body; /* to */ eol_line(11)=msg->callid->body; /* callid */ eol_line(12)=get_from(msg)->tag_value; /* from tag */ eol_line(13)=get_to(msg)->tag_value; /* to tag */ eol_line(14)=get_cseq(msg)->number; /* cseq number */ eol_line(15).s=id_buf; /* hash:label */ s = int2str(hash_index, &l); if (l+1>=IDBUF_LEN) { LM_ERR("too big hash\n"); goto error; } memcpy(id_buf, s, l); id_buf[l]=':'; eol_line(15).len=l+1; s = int2str(label, &l); if (l+1+eol_line(15).len>=IDBUF_LEN) { LM_ERR("too big label\n"); goto error; } memcpy(id_buf+eol_line(15).len, s, l); eol_line(15).len+=l; eol_line(16) = route.len ? route : empty_param; eol_line(17) = next_hop; eol_line(18) = append; eol_line(19) = body; /* success */ return 1; error: /* 0 would lead to immediate script exit -- -1 returns * with 'false' to script processing */ return -1; }
/* returns: 0/1 (false/true) or -1 on error, -127 EXPR_DROP */ static int eval_elem(struct expr* e, struct sip_msg* msg, pv_value_t *val) { struct sip_uri uri; int ret; int retl; int retr; int ival; pv_value_t lval; pv_value_t rval; char *p; ret=E_BUG; if (e->type!=ELEM_T){ LM_CRIT("invalid type\n"); goto error; } if(val) memset(val, 0, sizeof(pv_value_t)); switch(e->left.type){ case METHOD_O: ret=comp_strval(msg, e->op, &msg->first_line.u.request.method, &e->right); break; case URI_O: if(msg->new_uri.s){ if (e->right.type==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &msg->new_uri, &e->right); } }else{ if (e->right.type==MYSELF_ST){ if (parse_sip_msg_uri(msg)<0) ret=-1; else ret=check_self_op(e->op, &msg->parsed_uri.host, msg->parsed_uri.port_no? msg->parsed_uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &msg->first_line.u.request.uri, &e->right); } } break; case FROM_URI_O: if (parse_from_header(msg)<0){ LM_ERR("bad or missing From: header\n"); goto error; } if (e->right.type==MYSELF_ST){ if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len, &uri) < 0){ LM_ERR("bad uri in From:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &get_from(msg)->uri, &e->right); } break; case TO_URI_O: if ((msg->to==0) && ((parse_headers(msg, HDR_TO_F, 0)==-1) || (msg->to==0))){ LM_ERR("bad or missing To: header\n"); goto error; } /* to content is parsed automatically */ if (e->right.type==MYSELF_ST){ if (parse_uri(get_to(msg)->uri.s, get_to(msg)->uri.len, &uri) < 0){ LM_ERR("bad uri in To:\n"); goto error; } ret=check_self_op(e->op, &uri.host, uri.port_no?uri.port_no:SIP_PORT); }else{ ret=comp_strval(msg, e->op, &get_to(msg)->uri, &e->right); } break; case SRCIP_O: ret=comp_ip(msg, e->op, &msg->rcv.src_ip, &e->right); break; case DSTIP_O: ret=comp_ip(msg, e->op, &msg->rcv.dst_ip, &e->right); break; case NUMBER_O: ret=!(!e->right.v.n); /* !! to transform it in {0,1} */ break; case ACTION_O: ret=run_action_list( (struct action*)e->right.v.data, msg); if(val) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = ret; } if (ret<=0) ret=(ret==0)?EXPR_DROP:0; else ret=1; return ret; case EXPR_O: retl = retr = 0; memset(&lval, 0, sizeof(pv_value_t)); memset(&rval, 0, sizeof(pv_value_t)); if(e->left.v.data) retl=eval_expr((struct expr*)e->left.v.data,msg,&lval); if(lval.flags == PV_VAL_NONE) { pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(e->op == BNOT_OP) { if(lval.flags&PV_VAL_INT) { if(val!=NULL) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = ~lval.ri; } pv_value_destroy(&lval); pv_value_destroy(&rval); return (val->ri)?1:0; } LM_ERR("binary NOT on non-numeric value\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(e->right.v.data) retr=eval_expr((struct expr*)e->right.v.data,msg,&rval); if(lval.flags&PV_TYPE_INT) { if(!(rval.flags&PV_VAL_INT)) { LM_ERR("invalid numeric operands\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(val!=NULL) val->flags = PV_TYPE_INT|PV_VAL_INT; ival = 0; switch(e->op) { case PLUS_OP: ival = lval.ri + rval.ri; break; case MINUS_OP: ival = lval.ri - rval.ri; break; case DIV_OP: if(rval.ri==0) { LM_ERR("divide by 0\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } else ival = lval.ri / rval.ri; break; case MULT_OP: ival = lval.ri * rval.ri; break; case MODULO_OP: if(rval.ri==0) { LM_ERR("divide by 0\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } else ival = lval.ri % rval.ri; break; case BAND_OP: ival = lval.ri & rval.ri; break; case BOR_OP: ival = lval.ri | rval.ri; break; case BXOR_OP: ival = lval.ri ^ rval.ri; break; default: LM_ERR("invalid int op %d\n", e->op); val->ri = 0; pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } pv_value_destroy(&lval); pv_value_destroy(&rval); if(val!=NULL) val->ri = ival; return (ival)?1:0; } else { if(!(rval.flags&PV_VAL_STR)) { LM_ERR("invalid string operands\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(e->op != PLUS_OP) { LM_ERR("invalid string operator %d\n", e->op); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } if(val==NULL) { ret = (lval.rs.len>0 || rval.rs.len>0); pv_value_destroy(&lval); pv_value_destroy(&rval); return ret; } val->rs.s=(char*)pkg_malloc((lval.rs.len+rval.rs.len+1) *sizeof(char)); if(val->rs.s==0) { LM_ERR("no more memory\n"); pv_value_destroy(&lval); pv_value_destroy(&rval); return 0; } val->flags = PV_VAL_PKG|PV_VAL_STR; memcpy(val->rs.s, lval.rs.s, lval.rs.len); memcpy(val->rs.s+lval.rs.len, rval.rs.s, rval.rs.len); val->rs.len = lval.rs.len + rval.rs.len; val->rs.s[val->rs.len] = '\0'; pv_value_destroy(&lval); pv_value_destroy(&rval); return 1; } break; case SRCPORT_O: ret=comp_no(msg->rcv.src_port, e->right.v.data, /* e.g., 5060 */ e->op, /* e.g. == */ e->right.type /* 5060 is number */); break; case DSTPORT_O: ret=comp_no(msg->rcv.dst_port, e->right.v.data, e->op, e->right.type); break; case PROTO_O: ret=comp_no(msg->rcv.proto, e->right.v.data, e->op, e->right.type); break; case AF_O: ret=comp_no(msg->rcv.src_ip.af, e->right.v.data, e->op, e->right.type); break; case RETCODE_O: ret=comp_no(return_code, e->right.v.data, e->op, e->right.type); break; case MSGLEN_O: ret=comp_no(msg->len, e->right.v.data, e->op, e->right.type); break; case STRINGV_O: if(val) { val->flags = PV_VAL_STR; val->rs = e->left.v.s; } /* optimization for no dup ?!?! */ return (e->left.v.s.len>0)?1:0; case NUMBERV_O: if(val) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = e->left.v.n; } ret=!(!e->left.v.n); /* !! to transform it in {0,1} */ return ret; case SCRIPTVAR_O: if(e->op==NO_OP) { memset(&rval, 0, sizeof(pv_value_t)); if(pv_get_spec_value(msg, e->right.v.spec, &rval)==0) { if(rval.flags==PV_VAL_NONE || (rval.flags&PV_VAL_NULL) || (rval.flags&PV_VAL_EMPTY) || ((rval.flags&PV_TYPE_INT)&&rval.ri==0)) { pv_value_destroy(&rval); return 0; } if(rval.flags&PV_TYPE_INT) { pv_value_destroy(&rval); return 1; } if(rval.rs.len!=0) { pv_value_destroy(&rval); return 1; } pv_value_destroy(&rval); } return 0; } if(e->op==VALUE_OP) { if(pv_get_spec_value(msg, e->left.v.spec, &lval)==0) { if(val!=NULL) memcpy(val, &lval, sizeof(pv_value_t)); if(lval.flags&PV_VAL_STR) { if(!((lval.flags&PV_VAL_PKG) || (lval.flags&PV_VAL_SHM))) { if(val!=NULL) { /* do pkg duplicate */ p = (char*)pkg_malloc((val->rs.len+1) *sizeof(char)); if(p==0) { LM_ERR("no more pkg memory\n"); memset(val, 0, sizeof(pv_value_t)); return 0; } memcpy(p, val->rs.s, val->rs.len); p[val->rs.len] = 0; val->rs.s = p; val->flags|= PV_VAL_PKG; } } return 1; } if(lval.flags==PV_VAL_NONE || (lval.flags & PV_VAL_NULL) || (lval.flags & PV_VAL_EMPTY)) return 0; if(lval.flags&PV_TYPE_INT) return (lval.ri!=0); else return (lval.rs.len>0); } return 0; } ret=comp_scriptvar(msg, e->op, &e->left, &e->right); break; default: LM_CRIT("invalid operand %d\n", e->left.type); } if(val) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = ret; } return ret; error: if(val) { val->flags = PV_TYPE_INT|PV_VAL_INT; val->ri = -1; } return -1; }
/* change the r-uri if it is a PSTN format */ static int prefix2domain(struct sip_msg* msg, int mode, int sd_en) { str *d, p, all={"*",1}; int plen; struct sip_uri uri; if(msg==NULL) { LM_ERR("received null msg\n"); return -1; } /* parse the uri, if not yet */ if(msg->parsed_uri_ok==0) if(parse_sip_msg_uri(msg)<0) { LM_ERR("failed to parse the R-URI\n"); return -1; } /* if the user part begin with the prefix for PSTN users, extract the code*/ if (msg->parsed_uri.user.len<=0) { LM_DBG("user part of the message is empty\n"); return -1; } if(prefix.len>0) { if (msg->parsed_uri.user.len<=prefix.len) { LM_DBG("user part is less than prefix\n"); return -1; } if(strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0) { LM_DBG("PSTN prefix did not matched\n"); return -1; } } if(prefix.len>0 && prefix.len < msg->parsed_uri.user.len && strncasecmp(prefix.s, msg->parsed_uri.user.s, prefix.len)!=0) { LM_DBG("PSTN prefix did not matched\n"); return -1; } p.s = msg->parsed_uri.user.s + prefix.len; p.len = msg->parsed_uri.user.len - prefix.len; lock_start_read( pdt_lock ); if(sd_en==2) { /* take the domain from FROM uri as sdomain */ if(parse_from_header(msg)<0 || msg->from == NULL || get_from(msg)==NULL) { LM_ERR("cannot parse FROM header\n"); goto error; } memset(&uri, 0, sizeof(struct sip_uri)); if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0) { LM_ERR("failed to parse From uri\n"); goto error; } /* find the domain that corresponds to this prefix */ plen = 0; if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL) { plen = 0; if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL) { LM_INFO("no prefix found in [%.*s]\n", p.len, p.s); goto error; } } } else if(sd_en==1) { /* take the domain from FROM uri as sdomain */ if(parse_from_header(msg)<0 || msg->from == NULL || get_from(msg)==NULL) { LM_ERR("ERROR cannot parse FROM header\n"); goto error; } memset(&uri, 0, sizeof(struct sip_uri)); if (parse_uri(get_from(msg)->uri.s, get_from(msg)->uri.len , &uri)<0) { LM_ERR("failed to parse From uri\n"); goto error; } /* find the domain that corresponds to this prefix */ plen = 0; if((d=pdt_get_domain(*_ptree, &uri.host, &p, &plen))==NULL) { LM_INFO("no prefix found in [%.*s]\n", p.len, p.s); goto error; } } else { /* find the domain that corresponds to this prefix */ plen = 0; if((d=pdt_get_domain(*_ptree, &all, &p, &plen))==NULL) { LM_INFO("no prefix found in [%.*s]\n", p.len, p.s); goto error; } } /* update the new uri */ if(update_new_uri(msg, plen, d, mode)<0) { LM_ERR("new_uri cannot be updated\n"); goto error; } lock_stop_read( pdt_lock ); return 1; error: lock_stop_read( pdt_lock ); return -1; }
int i_enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service) { char *user_s; int user_len, i, j; char name[MAX_DOMAIN_SIZE]; char apex[MAX_COMPONENT_SIZE + 1]; char separator[MAX_COMPONENT_SIZE + 1]; int sdl = 0; /* subdomain location: infrastructure enum offset */ int cc_len; struct rdata* head; char string[MAX_NUM_LEN]; str *suffix, *service; suffix = (str*)_suffix; service = (str*)_service; if (parse_sip_msg_uri(_msg) < 0) { LM_ERR("Parsing of R-URI failed\n"); return -1; } if (is_e164(&(_msg->parsed_uri.user)) == -1) { LM_ERR("R-URI user is not an E164 number\n"); return -1; } user_s = _msg->parsed_uri.user.s; user_len = _msg->parsed_uri.user.len; /* make sure we don't run out of space in strings */ if (( 2*user_len + MAX_COMPONENT_SIZE + MAX_COMPONENT_SIZE + 4) > MAX_DOMAIN_SIZE) { LM_ERR("Strings too long\n"); return -1; } if ( i_branchlabel.len > MAX_COMPONENT_SIZE ) { LM_ERR("i_branchlabel too long\n"); return -1; } if ( suffix->len > MAX_COMPONENT_SIZE ) { LM_ERR("Suffix too long\n"); return -1; } memcpy(&(string[0]), user_s, user_len); string[user_len] = (char)0; /* Set up parameters as for user-enum */ memcpy(apex, suffix->s , suffix->len); apex[suffix->len] = (char)0; sdl = 0; /* where to insert i-enum separator */ separator[0] = 0; /* don't insert anything */ cc_len = cclen(string + 1); if (!strncasecmp(i_bl_alg.s,"ebl",i_bl_alg.len)) { sdl = cc_len; /* default */ j = 0; memcpy(name, i_branchlabel.s, i_branchlabel.len); j += i_branchlabel.len; name[j++] = '.'; for (i = cc_len ; i > 0; i--) { name[j++] = user_s[i]; name[j++] = '.'; } memcpy(name + j, suffix->s, suffix->len + 1); LM_DBG("Looking for EBL record for %s.\n", name); head = get_record(name, T_EBL, RES_ONLY_TYPE); if (head == 0) { LM_DBG("No EBL found for %s. Defaulting to user ENUM.\n",name); } else { struct ebl_rdata* ebl; ebl = (struct ebl_rdata *) head->rdata; LM_DBG("EBL record for %s is %d / %.*s / %.*s.\n", name, ebl->position, (int)ebl->separator_len, ebl->separator,(int)ebl->apex_len, ebl->apex); if ((ebl->apex_len > MAX_COMPONENT_SIZE) || (ebl->separator_len > MAX_COMPONENT_SIZE)) { LM_ERR("EBL strings too long\n"); return -1; } if (ebl->position > 15) { LM_ERR("EBL position too large (%d)\n", ebl->position); return -1; } sdl = ebl->position; memcpy(separator, ebl->separator, ebl->separator_len); separator[ebl->separator_len] = 0; memcpy(apex, ebl->apex, ebl->apex_len); apex[ebl->apex_len] = 0; free_rdata_list(head); } } else if (!strncasecmp(i_bl_alg.s,"txt",i_bl_alg.len)) { sdl = cc_len; /* default */ memcpy(separator, i_branchlabel.s, i_branchlabel.len); separator[i_branchlabel.len] = 0; /* no change to apex */ j = 0; memcpy(name, i_branchlabel.s, i_branchlabel.len); j += i_branchlabel.len; name[j++] = '.'; for (i = cc_len ; i > 0; i--) { name[j++] = user_s[i]; name[j++] = '.'; } memcpy(name + j, suffix->s, suffix->len + 1); head = get_record(name, T_TXT, RES_ONLY_TYPE); if (head == 0) { LM_DBG("TXT found for %s. Defaulting to %d\n", name, cc_len); } else { sdl = atoi(((struct txt_rdata*)head->rdata)->txt[0].cstr); LM_DBG("TXT record for %s is %d.\n", name, sdl); if ((sdl < 0) || (sdl > 10)) { LM_ERR("Sdl %d out of bounds. Set back to cc_len.\n", sdl); sdl = cc_len; } free_rdata_list(head); } } else { /* defaults to CC */ sdl = cc_len; memcpy(separator, i_branchlabel.s, i_branchlabel.len); separator[i_branchlabel.len] = 0; /* no change to apex */ } j = 0; sdl++; /* to avoid comparing i to (sdl+1) */ for (i = user_len - 1; i > 0; i--) { name[j] = user_s[i]; name[j + 1] = '.'; j = j + 2; if (separator[0] && (i == sdl)) { /* insert the I-ENUM separator here? */ strcpy(name + j, separator); /* we've checked string sizes. */ j += strlen(separator); name[j++] = '.'; } } memcpy(name + j, apex, strlen(apex)+1); return do_query(_msg, string, name, service); }
int rls_handle_subscribe(struct sip_msg* msg, str watcher_user, str watcher_domain) { subs_t subs; pres_ev_t* event = NULL; int err_ret = -1; int ret = to_presence_code; str* contact = NULL; xmlDocPtr doc = NULL; xmlNodePtr service_node = NULL; unsigned int hash_code=0; int to_tag_gen = 0; event_t* parsed_event; param_t* ev_param = NULL; str reason; int rt; str rlsubs_did = {0, 0}; memset(&subs, 0, sizeof(subs_t)); /** sanity checks - parse all headers */ if (parse_headers(msg, HDR_EOH_F, 0)<-1) { LM_ERR("failed parsing all headers\n"); if (slb.freply(msg, 400, &pu_400_rpl) < 0) { LM_ERR("while sending 400 reply\n"); return -1; } return 0; } /* check for To and From headesr */ if(parse_to_uri(msg)<0 || parse_from_uri(msg)<0) { LM_ERR("failed to find To or From headers\n"); if (slb.freply(msg, 400, &pu_400_rpl) < 0) { LM_ERR("while sending 400 reply\n"); return -1; } return 0; } if(get_from(msg)->tag_value.s ==NULL || get_from(msg)->tag_value.len==0) { LM_ERR("no from tag value present\n"); return -1; } if(msg->callid==NULL || msg->callid->body.s==NULL) { LM_ERR("cannot find callid header\n"); return -1; } if(parse_sip_msg_uri(msg)<0) { LM_ERR("failed parsing Request URI\n"); return -1; } /* check for header 'Support: eventlist' */ if(msg->supported==NULL) { LM_DBG("supported header not found - not for rls\n"); goto forpresence; } if(parse_supported(msg)<0) { LM_ERR("failed to parse supported headers\n"); return -1; } if(!(get_supported(msg) & F_SUPPORTED_EVENTLIST)) { LM_DBG("No support for 'eventlist' - not for rls\n"); goto forpresence; } /* inspecting the Event header field */ if(msg->event && msg->event->body.len > 0) { if (!msg->event->parsed && (parse_event(msg->event) < 0)) { LM_ERR("cannot parse Event header\n"); goto error; } if(! ( ((event_t*)msg->event->parsed)->type & rls_events) ) { goto forpresence; } } else { goto bad_event; } /* search event in the list */ parsed_event = (event_t*)msg->event->parsed; event = pres_search_event(parsed_event); if(event==NULL) { goto bad_event; } subs.event= event; /* extract the id if any*/ ev_param= parsed_event->params.list; while(ev_param) { if(ev_param->name.len==2 && strncmp(ev_param->name.s, "id", 2)==0) { subs.event_id = ev_param->body; break; } ev_param= ev_param->next; } /* extract dialog information from message headers */ if(pres_extract_sdialog_info(&subs, msg, rls_max_expires, &to_tag_gen, rls_server_address, watcher_user, watcher_domain)<0) { LM_ERR("bad subscribe request\n"); goto error; } hash_code = core_hash(&subs.callid, &subs.to_tag, hash_size); if (CONSTR_RLSUBS_DID(&subs, &rlsubs_did) < 0) { LM_ERR("cannot build rls subs did\n"); goto error; } subs.updated = core_hash(&rlsubs_did, NULL, 0) % (waitn_time * rls_notifier_poll_rate * rls_notifier_processes); if(get_to(msg)->tag_value.s==NULL || get_to(msg)->tag_value.len==0) { /* initial Subscribe */ /*verify if Request URI represents a list by asking xcap server*/ if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host, &subs.pres_uri)<0) { LM_ERR("while constructing uri from user and domain\n"); goto error; } if(rls_get_service_list(&subs.pres_uri, &subs.watcher_user, &subs.watcher_domain, &service_node, &doc)<0) { LM_ERR("while attepmting to get a resource list\n"); goto error; } if(doc==NULL) { /* if not for RLS, pass it to presence serivce */ LM_DBG("list not found - searched for uri <%.*s>\n", subs.pres_uri.len, subs.pres_uri.s); goto forpresence; } /* if correct reply with 200 OK */ if(reply_200(msg, &subs.local_contact, subs.expires)<0) goto error; subs.local_cseq = 0; if(subs.expires != 0) { subs.version = 1; if (dbmode==RLS_DB_ONLY) { rt=insert_rlsdb( &subs ); } else { rt=pres_insert_shtable(rls_table, hash_code, &subs); } if (rt<0) { LM_ERR("while adding new subscription\n"); goto error; } } } else { /* search if a stored dialog */ if ( dbmode == RLS_DB_ONLY ) { if (rls_dbf.start_transaction) { if (rls_dbf.start_transaction(rls_db, DB_LOCKING_WRITE) < 0) { LM_ERR("in start_transaction\n"); goto error; } } rt = get_dialog_subscribe_rlsdb(&subs); if (rt <= 0) { LM_DBG("subscription dialog not found for <%.*s@%.*s>\n", subs.watcher_user.len, subs.watcher_user.s, subs.watcher_domain.len, subs.watcher_domain.s); if (rls_dbf.end_transaction) { if (rls_dbf.end_transaction(rls_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } goto forpresence; } else if(rt>=400) { reason = (rt==400)?pu_400_rpl:stale_cseq_rpl; if (slb.freply(msg, 400, &reason) < 0) { LM_ERR("while sending reply\n"); goto error; } if (rls_dbf.end_transaction) { if (rls_dbf.end_transaction(rls_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } ret = 0; goto stop; } /* if correct reply with 200 OK */ if(reply_200(msg, &subs.local_contact, subs.expires)<0) goto error; if (update_dialog_subscribe_rlsdb(&subs) < 0) { LM_ERR("while updating resource list subscription\n"); goto error; } if (rls_dbf.end_transaction) { if (rls_dbf.end_transaction(rls_db) < 0) { LM_ERR("in end_transaction\n"); goto error; } } } else { lock_get(&rls_table[hash_code].lock); if(pres_search_shtable(rls_table, subs.callid, subs.to_tag, subs.from_tag, hash_code)==NULL) { lock_release(&rls_table[hash_code].lock); LM_DBG("subscription dialog not found for <%.*s@%.*s>\n", subs.watcher_user.len, subs.watcher_user.s, subs.watcher_domain.len, subs.watcher_domain.s); goto forpresence; } lock_release(&rls_table[hash_code].lock); /* if correct reply with 200 OK */ if(reply_200(msg, &subs.local_contact, subs.expires)<0) goto error; rt = update_rlsubs(&subs, hash_code); if(rt<0) { LM_ERR("while updating resource list subscription\n"); goto error; } if(rt>=400) { reason = (rt==400)?pu_400_rpl:stale_cseq_rpl; if (slb.freply(msg, 400, &reason) < 0) { LM_ERR("while sending reply\n"); goto error; } ret = 0; goto stop; } } if(rls_get_service_list(&subs.pres_uri, &subs.watcher_user, &subs.watcher_domain, &service_node, &doc)<0) { LM_ERR("failed getting resource list\n"); goto error; } if(doc==NULL) { /* warning: no document returned?!?! */ LM_WARN("no document returned for uri <%.*s>\n", subs.pres_uri.len, subs.pres_uri.s); goto done; } } if (dbmode != RLS_DB_ONLY) { /* sending notify with full state */ if(send_full_notify(&subs, service_node, &subs.pres_uri, hash_code)<0) { LM_ERR("failed sending full state notify\n"); goto error; } } /* send subscribe requests for all in the list */ if(resource_subscriptions(&subs, service_node)< 0) { LM_ERR("failed sending subscribe requests to resources in list\n"); goto error; } if (dbmode !=RLS_DB_ONLY) remove_expired_rlsubs(&subs, hash_code); done: ret = 1; stop: forpresence: if(contact!=NULL) { if(contact->s!=NULL) pkg_free(contact->s); pkg_free(contact); } if(subs.pres_uri.s!=NULL) pkg_free(subs.pres_uri.s); if(subs.record_route.s!=NULL) pkg_free(subs.record_route.s); if(doc!=NULL) xmlFreeDoc(doc); if (rlsubs_did.s != NULL) pkg_free(rlsubs_did.s); return ret; bad_event: err_ret = 0; if(reply_489(msg)<0) { LM_ERR("failed sending 489 reply\n"); err_ret = -1; } error: LM_ERR("occured in rls_handle_subscribe\n"); if(contact!=NULL) { if(contact->s!=NULL) pkg_free(contact->s); pkg_free(contact); } if(subs.pres_uri.s!=NULL) pkg_free(subs.pres_uri.s); if(subs.record_route.s!=NULL) pkg_free(subs.record_route.s); if(doc!=NULL) xmlFreeDoc(doc); if (rlsubs_did.s != NULL) pkg_free(rlsubs_did.s); if (rls_dbf.abort_transaction) { if (rls_dbf.abort_transaction(rls_db) < 0) LM_ERR("in abort_transaction\n"); } return err_ret; }
/* * Check from AAA server if a user belongs to a group. User-Name is digest * username or digest username@realm, SIP-Group is group, and Service-Type * is Group-Check. SIP-Group is SER specific attribute and Group-Check is * SER specific service type value. */ int aaa_is_user_in(struct sip_msg* _m, char* _hf, char* _group) { str *grp, user_name, user, domain; dig_cred_t* cred = 0; int hf_type; uint32_t service; aaa_message *send = NULL, *received = NULL; struct hdr_field* h; struct sip_uri *turi; grp = (str*)_group; /* via fixup */ hf_type = (int)(long)_hf; turi = 0; switch(hf_type) { case 1: /* Request-URI */ if(parse_sip_msg_uri(_m)<0) { LM_ERR("failed to get Request-URI\n"); return -1; } turi = &_m->parsed_uri; break; case 2: /* To */ if((turi=parse_to_uri(_m))==NULL) { LM_ERR("failed to get To URI\n"); return -1; } break; case 3: /* From */ if((turi=parse_from_uri(_m))==NULL) { LM_ERR("failed to get From URI\n"); return -1; } break; case 4: /* Credentials */ get_authorized_cred(_m->authorization, &h); if (!h) { get_authorized_cred(_m->proxy_auth, &h); if (!h) { LM_ERR("no authorized" " credentials found (error in scripts)\n"); return -4; } } cred = &((auth_body_t*)(h->parsed))->digest; break; } if (hf_type != 4) { user = turi->user; domain = turi->host; } else { user = cred->username.user; domain = *GET_REALM(cred); } if (user.s == NULL || user.len == 0) { LM_DBG("no username part\n"); return -1; } if (use_domain) { user_name.len = user.len + domain.len + 1; user_name.s = (char*)pkg_malloc(user_name.len); if (!user_name.s) { LM_ERR("no pkg memory left\n"); return -6; } memcpy(user_name.s, user.s, user.len); user_name.s[user.len] = '@'; memcpy(user_name.s + user.len + 1, domain.s, domain.len); } else { user_name = user; } if ((send = proto.create_aaa_message(conn, AAA_AUTH)) == NULL) { LM_ERR("failed to create new aaa message for auth \n"); return -1; } if (proto.avp_add(conn, send, &attrs[A_USER_NAME], user_name.s, user_name.len, 0)) { proto.destroy_aaa_message(conn, send); if (use_domain) pkg_free(user_name.s); return -7; } if (use_domain) pkg_free(user_name.s); if (proto.avp_add(conn, send, &attrs[A_SIP_GROUP], grp->s, grp->len, 0)) { proto.destroy_aaa_message(conn, send); LM_ERR("failed to add Sip-Group attribute\n"); return -8; } service = vals[V_GROUP_CHECK].value; if (proto.avp_add(conn, send, &attrs[A_SERVICE_TYPE], &service, -1, 0)) { proto.destroy_aaa_message(conn, send); LM_ERR("failed to add Service-Type attribute\n"); return -8; } /* Add CALL-ID in Acct-Session-Id Attribute */ if ((parse_headers(_m, HDR_CALLID_F, 0) == -1 || _m->callid == NULL) && _m->callid == NULL) { proto.destroy_aaa_message(conn, send); LM_ERR("msg parsing failed or callid not present"); return -10; } if (proto.avp_add(conn, send, &attrs[A_ACCT_SESSION_ID], _m->callid->body.s, _m->callid->body.len, 0)) { proto.destroy_aaa_message(conn, send); LM_ERR("unable to add CALL-ID attribute\n"); return -11; } if (!proto.send_aaa_request(conn, send, &received)) { LM_DBG("Success\n"); proto.destroy_aaa_message(conn, send); proto.destroy_aaa_message(conn, received); return 1; } else { LM_DBG("Failure\n"); proto.destroy_aaa_message(conn, send); proto.destroy_aaa_message(conn, received); return -12; } }
static int pv_auth_check(sip_msg_t *msg, char *realm, char *passwd, char *flags, char *checks) { int vflags = 0; int vchecks = 0; str srealm = {0, 0}; str spasswd = {0, 0}; int ret; hdr_field_t *hdr; sip_uri_t *uri = NULL; sip_uri_t *turi = NULL; sip_uri_t *furi = NULL; if(msg==NULL) { LM_ERR("invalid msg parameter\n"); return AUTH_ERROR; } if ((msg->REQ_METHOD == METHOD_ACK) || (msg->REQ_METHOD == METHOD_CANCEL)) { return AUTH_OK; } if(realm==NULL || passwd==NULL || flags==NULL || checks==NULL) { LM_ERR("invalid parameters\n"); return AUTH_ERROR; } if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); return AUTH_ERROR; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); return AUTH_ERROR; } if (get_str_fparam(&spasswd, msg, (fparam_t*)passwd) < 0) { LM_ERR("failed to get passwd value\n"); return AUTH_ERROR; } if(spasswd.len==0) { LM_ERR("invalid password value - empty content\n"); return AUTH_ERROR; } if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); return AUTH_ERROR; } if (get_int_fparam(&vchecks, msg, (fparam_t*)checks) < 0) { LM_ERR("invalid checks value\n"); return AUTH_ERROR; } LM_DBG("realm [%.*s] flags [%d] checks [%d]\n", srealm.len, srealm.s, vflags, vchecks); if(msg->REQ_METHOD==METHOD_REGISTER) ret = pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_AUTHORIZATION_T, &msg->first_line.u.request.method); else ret = pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_PROXYAUTH_T, &msg->first_line.u.request.method); if(ret==AUTH_OK && (vflags&AUTH_CHECK_ID_F)) { hdr = (msg->proxy_auth==0)?msg->authorization:msg->proxy_auth; srealm = ((auth_body_t*)(hdr->parsed))->digest.username.user; if((furi=parse_from_uri(msg))==NULL) return AUTH_ERROR; if(msg->REQ_METHOD==METHOD_REGISTER || msg->REQ_METHOD==METHOD_PUBLISH) { if((turi=parse_to_uri(msg))==NULL) return AUTH_ERROR; uri = turi; } else { uri = furi; } if(srealm.len!=uri->user.len || strncmp(srealm.s, uri->user.s, srealm.len)!=0) return AUTH_USER_MISMATCH; if(msg->REQ_METHOD==METHOD_REGISTER || msg->REQ_METHOD==METHOD_PUBLISH) { /* check from==to */ if(furi->user.len!=turi->user.len || strncmp(furi->user.s, turi->user.s, furi->user.len)!=0) return AUTH_USER_MISMATCH; if(auth_use_domain!=0 && (furi->host.len!=turi->host.len || strncmp(furi->host.s, turi->host.s, furi->host.len)!=0)) return AUTH_USER_MISMATCH; /* check r-uri==from for publish */ if(msg->REQ_METHOD==METHOD_PUBLISH) { if(parse_sip_msg_uri(msg)<0) return AUTH_ERROR; uri = &msg->parsed_uri; if(furi->user.len!=uri->user.len || strncmp(furi->user.s, uri->user.s, furi->user.len)!=0) return AUTH_USER_MISMATCH; if(auth_use_domain!=0 && (furi->host.len!=uri->host.len || strncmp(furi->host.s, uri->host.s, furi->host.len)!=0)) return AUTH_USER_MISMATCH; } } return AUTH_OK; } return ret; }