static int pv_proxy_authenticate(struct sip_msg *msg, char* realm, char *passwd, char *flags) { int vflags = 0; str srealm = {0, 0}; str spasswd = {0, 0}; if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if (get_str_fparam(&spasswd, msg, (fparam_t*)passwd) < 0) { LM_ERR("failed to get passwd value\n"); goto error; } if(spasswd.len==0) { LM_ERR("invalid password value - empty content\n"); goto error; } if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); goto error; } return pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_PROXYAUTH_T, &msg->first_line.u.request.method); error: return AUTH_ERROR; }
int autheph_authenticate(struct sip_msg *_m, char *_username, char *_password) { str susername, spassword; if (_m == NULL || _username == NULL || _password == NULL) { LM_ERR("invalid parameters\n"); return AUTH_ERROR; } if (get_str_fparam(&susername, _m, (fparam_t*)_username) < 0) { LM_ERR("failed to get username value\n"); return AUTH_ERROR; } if (get_str_fparam(&spassword, _m, (fparam_t*)_password) < 0) { LM_ERR("failed to get password value\n"); return AUTH_ERROR; } return ki_autheph_authenticate(_m, &susername, &spassword); }
/** * @brief Small wrapper around send_reply */ static int w_send_reply(struct sip_msg* msg, char* p1, char* p2) { int code; str reason; if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) { code = default_code; } if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) { reason = default_reason; } return send_reply(msg, code, &reason); }
static int sca_call_info_update_3_f(sip_msg_t* msg, char* p1, char* p2, char * p3) { str uri_to = STR_NULL; str uri_from = STR_NULL; int update_mask = SCA_CALL_INFO_SHARED_BOTH; if (get_int_fparam(&update_mask, msg, (fparam_t *) p1) < 0) { LM_ERR("sca_call_info_update: argument 1: bad value " "(integer expected)\n"); return (-1); } if(get_str_fparam(&uri_to, msg, (gparam_p)p2)!=0) { LM_ERR("unable to get value from param pvar_to\n"); return -1; } if(get_str_fparam(&uri_from, msg, (gparam_p)p3)!=0) { LM_ERR("unable to get value from param pvar_from\n"); return -1; } return sca_call_info_update(msg, update_mask, &uri_to, &uri_from); }
inline static int w_t_reply(struct sip_msg* msg, char* p1, char* p2) { struct cell *t; int code, ret = -1; str reason; char* r; if (msg->REQ_METHOD==METHOD_ACK) { LOG(L_WARN, "WARNING: t_reply: ACKs are not replied\n"); return -1; } if (t_check( msg , 0 )==-1) return -1; t=get_t(); if (!t) { LOG(L_ERR, "ERROR: t_reply: cannot send a t_reply to a message " "for which no T-state has been established\n"); return -1; } if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) { code = default_code; } if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) { reason = default_reason; } r = as_asciiz(&reason); if (r == NULL) r = default_reason.s; /* if called from reply_route, make sure that unsafe version * is called; we are already in a mutex and another mutex in * the safe version would lead to a deadlock */ if (rmode==MODE_ONFAILURE) { DBG("DEBUG: t_reply_unsafe called from w_t_reply\n"); ret = t_reply_unsafe(t, msg, code, r); } else if (rmode==MODE_REQUEST) { ret = t_reply( t, msg, code, r); } else { LOG(L_CRIT, "BUG: w_t_reply entered in unsupported mode\n"); ret = -1; } if (r) pkg_free(r); return ret; }
/* * Call enum_query_2 with given suffix and service. */ int enum_query_2(struct sip_msg* _msg, char* _suffix, char* _service) { str suffix, *service; if (get_str_fparam(&suffix, _msg, (fparam_t*)_suffix) != 0) { LM_ERR("unable to get suffix\n"); return -1; } service = (str*)_service; if ((service == NULL) || (service->len == 0)) { LM_ERR("invalid service parameter"); return -1; } return enum_query(_msg, &suffix, service); }
int autheph_check(struct sip_msg *_m, char *_realm) { str srealm; if (eph_auth_api.pre_auth == NULL) { LM_ERR("autheph_check() cannot be used without the auth " "module\n"); return AUTH_ERROR; } if (_m->REQ_METHOD == METHOD_ACK || _m->REQ_METHOD == METHOD_CANCEL) { return AUTH_OK; } if(_m == NULL || _realm == NULL) { LM_ERR("invalid parameters\n"); return AUTH_ERROR; } if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0) { LM_ERR("failed to get realm value\n"); return AUTH_ERROR; } if (srealm.len == 0) { LM_ERR("invalid realm parameter - empty value\n"); return AUTH_ERROR; } if (_m->REQ_METHOD == METHOD_REGISTER) { return digest_authenticate(_m, &srealm, HDR_AUTHORIZATION_T, &_m->first_line.u.request.method); } else { return digest_authenticate(_m, &srealm, HDR_PROXYAUTH_T, &_m->first_line.u.request.method); } }
int autheph_proxy(struct sip_msg *_m, char *_realm, char *_p2) { str srealm; if(_m == NULL || _realm == NULL) { LM_ERR("invalid parameters\n"); return AUTH_ERROR; } if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0) { LM_ERR("failed to get realm value\n"); return AUTH_ERROR; } return ki_autheph_proxy(_m, &srealm); }
int lookup_path_to_contact(struct sip_msg* _m, char* contact_uri) { ucontact_t* contact; str s_contact_uri; str path_dst; get_act_time(); if (get_str_fparam(&s_contact_uri, _m, (fparam_t*) contact_uri) < 0) { LM_ERR("failed to get RURI\n"); return -1; } LM_DBG("Looking up contact [%.*s]\n", s_contact_uri.len, s_contact_uri.s); if (ul.get_ucontact(NULL, &s_contact_uri, 0, 0, 0, &contact) == 0) { //get_contact returns with lock if (!VALID_CONTACT(contact, act_time)) { LM_DBG("Contact is not valid...ignoring\n"); ul.release_ucontact(contact); } else { LM_DBG("CONTACT FOUND and path is [%.*s]\n", contact->path.len, contact->path.s); if (get_path_dst_uri(&contact->path, &path_dst) < 0) { LM_ERR("failed to get dst_uri for Path\n"); ul.release_ucontact(contact); return -1; } if (set_path_vector(_m, &contact->path) < 0) { LM_ERR("failed to set path vector\n"); ul.release_ucontact(contact); return -1; } if (set_dst_uri(_m, &path_dst) < 0) { LM_ERR("failed to set dst_uri of Path\n"); ul.release_ucontact(contact); return -1; } ul.release_ucontact(contact); return 1; } } LM_DBG("no contact found for [%.*s]\n", s_contact_uri.len, s_contact_uri.s); return -1; }
static int w_sl_send_reply(struct sip_msg* msg, char* p1, char* p2) { int code, ret; str reason; char* r; if (get_int_fparam(&code, msg, (fparam_t*)p1) < 0) { code = default_code; } if (get_str_fparam(&reason, msg, (fparam_t*)p2) < 0) { reason = default_reason;; } r = as_asciiz(&reason); if (r == NULL) r = default_reason.s; ret = sl_send_reply(msg, code, r); if (r) pkg_free(r); return ret; }
static int append_reply(struct sip_msg* msg, char* p1, char* p2) { avp_ident_t ident, *avp; str hf; if (get_str_fparam(&hf, msg, (fparam_t*)p1) < 0) { ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p1)->orig); return -1; } if (p2) { avp = &((fparam_t*)p2)->v.avp; } else { ident.name.s = hf; ident.flags = AVP_NAME_STR; ident.index = 0; avp = &ident; } return (request_hf_helper(msg, &hf, avp, NULL, NULL, 0, 1, 1)); }
/* * Check if the username matches the username in credentials */ int is_user(struct sip_msg* _m, char* _user, char* _str2) { str s; struct hdr_field* h; auth_body_t* c; if (get_str_fparam(&s, _m, (fparam_t *)_user) < 0) { ERR("is_user: failed to recover parameter.\n"); return -1; } get_authorized_cred(_m->authorization, &h); if (!h) { get_authorized_cred(_m->proxy_auth, &h); if (!h) { LOG(L_ERR, "is_user(): No authorized credentials found (error in scripts)\n"); LOG(L_ERR, "is_user(): Call {www,proxy}_authorize before calling is_user function !\n"); return -1; } } c = (auth_body_t*)(h->parsed); if (!c->digest.username.user.len) { DBG("is_user(): Username not found in credentials\n"); return -1; } if (s.len != c->digest.username.user.len) { DBG("is_user(): Username length does not match\n"); return -1; } if (!memcmp(s.s, c->digest.username.user.s, s.len)) { DBG("is_user(): Username matches\n"); return 1; } else { DBG("is_user(): Username differs\n"); return -1; } }
static int set_sattr(struct sip_msg* msg, char* p1, char* p2) { avp_ident_t avpid; int_str value; if (get_avp_id(&avpid, (fparam_t*)p1, msg) < 0) { return -1; } if (get_str_fparam(&value.s, msg, (fparam_t*)p2) < 0) { ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p2)->orig); return -1; } if (add_avp(avpid.flags | AVP_NAME_STR | AVP_VAL_STR, avpid.name, value) != 0) { ERR("add_avp failed\n"); return -1; } return 1; }
/** * removes all SDP lines that begin with script provided prefix * @return -1 - error; 1 - found */ static int w_sdp_remove_line_by_prefix(sip_msg_t* msg, char* prefix, char* bar) { str prfx = {NULL, 0}; if(prefix==0) { LM_ERR("invalid parameters\n"); return -1; } if (get_str_fparam(&prfx, msg, (fparam_t*)prefix)) { LM_ERR("unable to determine prefix\n"); return -1; } LM_DBG("Removing SDP lines with prefix: %.*s\n", prfx.len, prfx.s); if ( sdp_remove_line_by_prefix(msg, &prfx) < 0) return -1; return 1; }
/* * Return true if the AOR in the Request-URI is registered, * it is similar to lookup but registered neither rewrites * the Request-URI nor appends branches */ int registered2(struct sip_msg* _m, char* _t, char* p2) { str uid, aor; urecord_t* r; ucontact_t* ptr; int res; if (get_str_fparam(&aor, _m, (fparam_t*)p2) != 0) { ERR("Unable to get the AOR value\n"); return -1; } if (get_to_uid(&uid, _m) < 0) return -1; ul.lock_udomain((udomain_t*)_t); res = ul.get_urecord((udomain_t*)_t, &uid, &r); if (res < 0) { ul.unlock_udomain((udomain_t*)_t); LOG(L_ERR, "registered(): Error while querying usrloc\n"); return -1; } if (res == 0) { ptr = r->contacts; while (ptr && (!VALID_CONTACT(ptr, act_time) || !VALID_AOR(ptr, aor))) { ptr = ptr->next; } if (ptr) { ul.unlock_udomain((udomain_t*)_t); DBG("registered(): '%.*s' found in usrloc\n", uid.len, ZSW(uid.s)); return 1; } } ul.unlock_udomain((udomain_t*)_t); DBG("registered(): '%.*s' not found in usrloc\n", uid.len, ZSW(uid.s)); return -1; }
int add_diversion(struct sip_msg* msg, char* r, char* s) { str div_hf; char *at; str* uri; str reason; if (get_str_fparam(&reason, msg, (fparam_t*)r) < 0) return -1; uri = &msg->first_line.u.request.uri; div_hf.len = DIVERSION_PREFIX_LEN + uri->len + DIVERSION_SUFFIX_LEN + reason.len + CRLF_LEN; div_hf.s = pkg_malloc(div_hf.len); if (!div_hf.s) { LOG(L_ERR, "add_diversion: No memory left\n"); return -1; } at = div_hf.s; memcpy(at, DIVERSION_PREFIX, DIVERSION_PREFIX_LEN); at += DIVERSION_PREFIX_LEN; memcpy(at, uri->s, uri->len); at += uri->len; memcpy(at, DIVERSION_SUFFIX, DIVERSION_SUFFIX_LEN); at += DIVERSION_SUFFIX_LEN; memcpy(at, reason.s, reason.len); at += reason.len; memcpy(at, CRLF, CRLF_LEN); if (add_diversion_helper(msg, &div_hf) < 0) { pkg_free(div_hf.s); return -1; } return 1; }
static int lookup_domain(struct sip_msg* msg, char* flags, char* fp) { str domain, tmp; domain_t* d; unsigned int track; int ret = -1; track = 0; if (get_str_fparam(&domain, msg, (fparam_t*)fp) != 0) { ERR("Cannot get domain name to lookup\n"); return -1; } tmp.s = pkg_malloc(domain.len); if (!tmp.s) { ERR("No memory left\n"); return -1; } memcpy(tmp.s, domain.s, domain.len); tmp.len = domain.len; strlower(&tmp); if (db_mode) { if (hash_lookup(&d, *active_hash, &tmp) == 1) { set_avp_list((unsigned long)flags, &d->attrs); ret = 1; } } else { if (db_load_domain(&d, (unsigned long)flags, &tmp) == 0) { set_avp_list((unsigned long)flags, &d->attrs); ret = 1; } } pkg_free(tmp.s); return ret; }
/*! * Wrapper for HTTP-Query (GET) */ static int w_http_query(struct sip_msg* _m, char* _url, char* _result) { int ret = 0; str url = {NULL, 0}; str result = {NULL, 0}; pv_spec_t *dst; pv_value_t val; if (get_str_fparam(&url, _m, (gparam_p)_url) != 0) { LM_ERR("URL undefined\n"); return -1; } ret = http_query(_m, url.s, &result, NULL); val.rs = result; val.flags = PV_VAL_STR; dst = (pv_spec_t *)_result; dst->setf(_m, &dst->pvp, (int)EQ_T, &val); if (result.s != NULL) pkg_free(result.s); return (ret==0)?-1:ret; }
/* * returns 1 if msg contains an AVP with the given name and value, * returns -1 otherwise */ static int attr_equals(struct sip_msg* msg, char* p1, char* p2) { avp_ident_t avpid; int_str value, avp_value; avp_t* avp; struct search_state st; if (get_avp_id(&avpid, (fparam_t*)p1, msg) < 0) { return -1; } if (p2 && get_str_fparam(&value.s, msg, (fparam_t*)p2) < 0) { ERR("Error while obtaining attribute value from '%s'\n", ((fparam_t*)p2)->orig); return -1; } avp = search_avp(avpid, &avp_value, &st); if (avp == 0) return -1; if (!p2) return 1; while (avp != 0) { if (avp->flags & AVP_VAL_STR) { if ((avp_value.s.len == value.s.len) && !memcmp(avp_value.s.s, value.s.s, avp_value.s.len)) { return 1; } } else { if (avp_value.n == str2s(value.s.s, value.s.len, 0)) { return 1; } } avp = search_next_avp(&st, &avp_value); } return -1; }
int read_reg_avps(struct sip_msg *m, char* _domain, char* fp) { urecord_t* r = NULL; struct ucontact *contact = NULL; udomain_t *d; str uid; if (!use_reg_avps()) return 1; d = (udomain_t*)_domain; if (get_str_fparam(&uid, m, (fparam_t*)fp) < 0) { ERR("invalid parameter\n"); return -1; } /* INFO("reading avps for uid=%.*s\n", uid.len, ZSW(uid.s)); */ lock_udomain(d); if (get_urecord(d, &uid, &r) != 0) { unlock_udomain(d); WARN("urecord not found\n"); return -1; } if (get_ucontact(r, &m->new_uri, &contact) != 0) { unlock_udomain(d); WARN("ucontact not found\n"); return -1; } load_reg_avps(contact); unlock_udomain(d); return 1; }
int autheph_check_to1(struct sip_msg *_m, char *_username) { str susername; if (_m == NULL || _username == NULL) { LM_ERR("invalid parameters\n"); return CHECK_ERROR; } if (get_str_fparam(&susername, _m, (fparam_t*)_username) < 0) { LM_ERR("failed to get username value\n"); return CHECK_ERROR; } if (susername.len == 0) { LM_ERR("invalid username parameter - empty value\n"); return CHECK_ERROR; } return check_to(_m, &susername); }
static int w_auth_challenge(struct sip_msg *msg, char* realm, char *flags) { int vflags = 0; str srealm = {0, 0}; if((msg->REQ_METHOD == METHOD_ACK) || (msg->REQ_METHOD == METHOD_CANCEL)) { return 1; } if(get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(srealm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if(get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) { LM_ERR("invalid flags value\n"); goto error; } if(msg->REQ_METHOD==METHOD_REGISTER) return auth_challenge(msg, &srealm, vflags, HDR_AUTHORIZATION_T); else return auth_challenge(msg, &srealm, vflags, HDR_PROXYAUTH_T); error: if(!(vflags&4)) { if(auth_send_reply(msg, 500, "Internal Server Error", 0, 0) <0 ) return -4; } return -1; }
/* * Converts URI, if it is tel URI, to SIP URI. Returns 1, if * conversion succeeded or if no conversion was needed, i.e., URI was not * tel URI. Returns -1, if conversion failed. Takes SIP URI hostpart from * second parameter and (if needed) writes the result to third paramater. */ int tel2sip(struct sip_msg* _msg, char* _uri, char* _hostpart, char* _res) { str uri, hostpart, tel_uri, sip_uri; char *at; int i, j, in_tel_parameters = 0; pv_spec_t *res; pv_value_t res_val; /* get parameters */ if (get_str_fparam(&uri, _msg, (fparam_t*)_uri) < 0) { LM_ERR("failed to get uri value\n"); } if (get_str_fparam(&hostpart, _msg, (fparam_t*)_hostpart) < 0) { LM_ERR("failed to get hostpart value\n"); } res = (pv_spec_t *)_res; /* check if anything needs to be done */ if (uri.len < 4) return 1; if (strncasecmp(uri.s, "tel:", 4) != 0) return 1; /* reserve memory for clean tel uri */ tel_uri.s = pkg_malloc(uri.len+1); if (tel_uri.s == 0) { LM_ERR("no more pkg memory\n"); return -1; } /* Remove visual separators before converting to SIP URI. Don't remove visual separators in TEL URI parameters (after the first ";") */ for (i=0, j=0; i < uri.len; i++) { if (in_tel_parameters == 0) { if (uri.s[i] == ';') in_tel_parameters = 1; } if (in_tel_parameters == 0) { if ((uri.s[i] != '-') && (uri.s[i] != '.') && (uri.s[i] != '(') && (uri.s[i] != ')')) tel_uri.s[j++] = tolower(uri.s[i]); } else { tel_uri.s[j++] = tolower(uri.s[i]); } } tel_uri.s[j] = '\0'; tel_uri.len = strlen(tel_uri.s); /* reserve memory for resulting sip uri */ sip_uri.len = 4 + tel_uri.len - 4 + 1 + hostpart.len + 1 + 10; sip_uri.s = pkg_malloc(sip_uri.len); if (sip_uri.s == 0) { LM_ERR("no more pkg memory\n"); pkg_free(tel_uri.s); return -1; } /* create resulting sip uri */ at = sip_uri.s; append_str(at, "sip:", 4); append_str(at, tel_uri.s + 4, tel_uri.len - 4); append_chr(at, '@'); append_str(at, hostpart.s, hostpart.len); append_chr(at, ';'); append_str(at, "user=phone", 10); /* tel_uri is not needed anymore */ pkg_free(tel_uri.s); /* set result pv value and write sip uri to result pv */ res_val.rs = sip_uri; res_val.flags = PV_VAL_STR; if (res->setf(_msg, &res->pvp, (int)EQ_T, &res_val) != 0) { LM_ERR("failed to set result pvar\n"); pkg_free(sip_uri.s); return -1; } /* free allocated pkg memory and return */ pkg_free(sip_uri.s); return 1; }
static int load_user_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp) { int_str name, v; str avp_name, avp_val; int i, type, n; db_key_t keys[1], cols[4]; db_res_t* res; db_val_t kv[1], *val; keys[0] = uid_column; kv[0].type = DB_STR; kv[0].nul = 0; if (get_str_fparam(&kv[0].val.str_val, msg, (fparam_t*)fp) < 0) { ERR("Unable to get UID\n"); return -1; } cols[0] = name_column; cols[1] = type_column; cols[2] = val_column; cols[3] = flags_column; if (db.use_table(con, user_attrs_table) < 0) { ERR("Error in use_table\n"); return -1; } if (db.query(con, keys, 0, kv, cols, 1, 4, 0, &res) < 0) { ERR("Error while quering database\n"); return -1; } n = 0; /* AVP names from DB are always strings */ flags |= AVP_NAME_STR; for(i = 0; i < res->n; i++) { /* reset val_str as the value could be an integer */ flags &= ~AVP_VAL_STR; val = res->rows[i].values; if (val[0].nul || val[1].nul || val[3].nul) { ERR("Skipping row containing NULL entries\n"); continue; } if ((val[3].val.int_val & DB_LOAD_SER) == 0) continue; n++; /* Get AVP name */ avp_name.s = (char*)val[0].val.string_val; avp_name.len = strlen(avp_name.s); name.s = avp_name; /* Get AVP type */ type = val[1].val.int_val; /* Test for NULL value */ if (val[2].nul) { avp_val.s = 0; avp_val.len = 0; } else { avp_val.s = (char*)val[2].val.string_val; avp_val.len = strlen(avp_val.s); } if (type == AVP_VAL_STR) { /* String AVP */ v.s = avp_val; flags |= AVP_VAL_STR; } else { /* Integer AVP */ str2int(&avp_val, (unsigned*)&v.n); } if (add_avp(flags, name, v) < 0) { ERR("Error while adding user attribute %.*s, skipping\n", avp_name.len, ZSW(avp_name.s)); continue; } } DBG("avp_db:load_attrs: %d user attributes found, %d loaded\n", res->n, n); db.free_result(con, res); return 1; }
static int w_ip_is_trusted(struct sip_msg* msg, char* _ip_set, char* _ip) { str ip_set_s, ip_s; struct ip_addr *ip, ip_buf; struct ip_set new_ip_set, *ip_set; struct ip_set_list_item *isli = NULL; int kind; kind = ((struct ip_set_param*)_ip_set)->kind; if (kind == IP_SET_PARAM_KIND_LOCAL) { if (get_str_fparam(&ip_set_s, msg, ((struct ip_set_param*)_ip_set)->u.local.fparam) < 0) { ERR(MODULE_NAME": ip_is_trusted: Error while obtaining ip_set parameter value\n"); return -1; } if (is_ip_set_name(&ip_set_s)) { isli = ip_set_list_find_by_name(ip_set_s); if (!isli) { ERR(MODULE_NAME": ip_is_trusted: ip set '%.*s' is not declared\n", ip_set_s.len, ip_set_s.s); return -1; } kind = IP_SET_PARAM_KIND_GLOBAL; goto force_global; } ip_set = &((struct ip_set_param*)_ip_set)->u.local.ip_set; } else { isli = ((struct ip_set_param*)_ip_set)->u.global.ip_set; force_global: if (!isli->ip_set) return -1; /* empty ip set */ if (unlikely(isli->ip_set != ip_set_list_local[isli->idx])) { /* global ip set has changed ? */ if (ip_set_list_local[isli->idx]) { if (atomic_dec_and_test(&ip_set_list_local[isli->idx]->refcnt)) { ip_set_destroy(&ip_set_list_local[isli->idx]->ip_set); shm_free(ip_set_list_local[isli->idx]); ip_set_list_local[isli->idx] = NULL; } } lock_get(&isli->read_lock); atomic_inc(&isli->ip_set->refcnt); ip_set_list_local[isli->idx] = isli->ip_set; lock_release(&isli->read_lock); } ip_set = &ip_set_list_local[isli->idx]->ip_set; } if (get_str_fparam(&ip_s, msg, (fparam_t*)_ip) < 0) { ERR(MODULE_NAME": ip_is_trusted: Error while obtaining ip parameter value\n"); return -1; } if (!ip_s.len || !ip_set_s.len) return -1; switch (ip_s.s[0]) { case 's': /* src */ case 'S': ip = &msg->rcv.src_ip; break; case 'd': /* dst */ case 'D': ip = &msg->rcv.dst_ip; break; case 'r': /* rcv */ case 'R': ip = &msg->rcv.bind_address->address; break; default: /* string -> ip */ if ( ((ip = str2ip(&ip_s))==0) && ((ip = str2ip6(&ip_s))==0) ){ ERR(MODULE_NAME": ip_is_trusted: string to ip conversion error '%.*s'\n", ip_s.len, ip_s.s); return -1; } ip_buf = *ip; ip = &ip_buf; /* value has been in static buffer */ break; } /* test if ip_set string has changed since last call */ if (kind == IP_SET_PARAM_KIND_LOCAL) { if (((struct ip_set_param*)_ip_set)->u.local.s.len != ip_set_s.len || memcmp(((struct ip_set_param*)_ip_set)->u.local.s.s, ip_set_s.s, ip_set_s.len) != 0) { ip_set_init(&new_ip_set, 0); if (ip_set_add_list(&new_ip_set, ip_set_s) < 0) { ip_set_destroy(&new_ip_set); return -1; }; if (((struct ip_set_param*)_ip_set)->u.local.sz < ip_set_s.len) { void *p; p = pkg_realloc(((struct ip_set_param*)_ip_set)->u.local.s.s, ip_set_s.len); if (!p) { ip_set_destroy(&new_ip_set); return E_OUT_OF_MEM; } ((struct ip_set_param*)_ip_set)->u.local.s.s = p; ((struct ip_set_param*)_ip_set)->u.local.sz = ip_set_s.len; } memcpy(((struct ip_set_param*)_ip_set)->u.local.s.s, ip_set_s.s, ip_set_s.len); ((struct ip_set_param*)_ip_set)->u.local.s.len = ip_set_s.len; ip_set_destroy(&((struct ip_set_param*)_ip_set)->u.local.ip_set); ((struct ip_set_param*)_ip_set)->u.local.ip_set = new_ip_set; } } /* ip_set_print(stderr, &ip_set); */ switch (ip_set_ip_exists(ip_set, ip)) { case IP_TREE_FIND_FOUND: case IP_TREE_FIND_FOUND_UPPER_SET: return 1; default: return -1; } }
static int load_uri_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp) { static char rad_msg[4096]; struct sip_uri puri; str uri, did, scheme; UINT4 service; VALUE_PAIR* send, *received; send = NULL; received = NULL; if (get_str_fparam(&uri, msg, (fparam_t*)fp) != 0) { ERR("Unable to get URI\n"); return -1; } if (parse_uri(uri.s, uri.len, &puri) < 0) { ERR("Error while parsing URI '%.*s'\n", uri.len, uri.s); return -1; } if (puri.host.len) { /* domain name is present */ if (dm_get_did(&did, &puri.host) < 0) { DBG("Cannot lookup DID for domain %.*s, using default value\n", puri.host.len, ZSW(puri.host.s)); did.s = DEFAULT_DID; did.len = sizeof(DEFAULT_DID) - 1; } } else { /* domain name is missing -- can be caused by tel: URI */ DBG("There is no domain name, using default value\n"); did.s = DEFAULT_DID; did.len = sizeof(DEFAULT_DID) - 1; } uri_type_to_str(puri.type, &scheme); service = vals[V_GET_URI_ATTRS].v; if (scheme.len) { if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_URI_SCHEME].v), scheme.s, scheme.len, VENDOR(attrs[A_SER_URI_SCHEME].v))) { ERR("Error while adding A_SER_URI_SCHEME\n"); goto error; } } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v), puri.user.s, puri.user.len, VENDOR(attrs[A_USER_NAME].v))) { ERR("Error while adding A_USER_NAME\n"); goto error; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_DID].v), did.s, did.len, VENDOR(attrs[A_SER_DID].v))) { ERR("Error while adding A_SER_DID\n"); goto error; } if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_SERVICE_TYPE].v), &vals[V_GET_URI_ATTRS].v, -1, VENDOR(attrs[A_SER_SERVICE_TYPE].v))) { ERR("Error adding A_SERVICE_TYPE\n"); goto error; } if (rc_auth(rh, 0, send, &received, rad_msg) != OK_RC) { DBG("load_uri_attrs: Failure\n"); goto error; } DBG("load_uri_attrs: Success\n"); rc_avpair_free(send); if (generate_avps(flags, received) < 0) { rc_avpair_free(received); goto error; } rc_avpair_free(received); return 1; error: if (send) rc_avpair_free(send); if (received) rc_avpair_free(send); return -1; }
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 && (vchecks&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; }
/* * Lookup contact in the database and rewrite Request-URI, * and filter them by aor */ int lookup2(struct sip_msg* msg, char* table, char* p2) { urecord_t* r; str uid; ucontact_t* ptr; int res; unsigned int nat; str new_uri, aor; fparam_t* fp; nat = 0; fp = (fparam_t*)p2; if (get_str_fparam(&aor, msg, (fparam_t*)p2) != 0) { ERR("Unable to get the AOR value\n"); return -1; } if (get_to_uid(&uid, msg) < 0) return -1; get_act_time(); ul.lock_udomain((udomain_t*)table); res = ul.get_urecord((udomain_t*)table, &uid, &r); if (res < 0) { ERR("Error while querying usrloc\n"); ul.unlock_udomain((udomain_t*)table); return -2; } if (res > 0) { DBG("'%.*s' Not found in usrloc\n", uid.len, ZSW(uid.s)); ul.unlock_udomain((udomain_t*)table); return -3; } ptr = r->contacts; while (ptr && (!VALID_CONTACT(ptr, act_time) || !VALID_AOR(ptr, aor))) ptr = ptr->next; if (ptr) { if (ptr->received.s && ptr->received.len) { if (received_to_uri){ if (add_received(&new_uri, &ptr->c, &ptr->received) < 0) { ERR("Out of memory\n"); return -4; } /* replace the msg uri */ if (msg->new_uri.s) pkg_free(msg->new_uri.s); msg->new_uri = new_uri; msg->parsed_uri_ok = 0; ruri_mark_new(); goto skip_rewrite_uri; } else if (set_dst_uri(msg, &ptr->received) < 0) { ul.unlock_udomain((udomain_t*)table); return -4; } } if (rewrite_uri(msg, &ptr->c) < 0) { ERR("Unable to rewrite Request-URI\n"); ul.unlock_udomain((udomain_t*)table); return -4; } if (ptr->sock) { set_force_socket(msg, ptr->sock); } skip_rewrite_uri: set_ruri_q(ptr->q); nat |= ptr->flags & FL_NAT; ptr = ptr->next; } else { /* All contacts expired */ ul.unlock_udomain((udomain_t*)table); return -5; } /* Append branches if enabled */ if (!append_branches) goto skip; while(ptr) { if (VALID_CONTACT(ptr, act_time) && VALID_AOR(ptr, aor)) { if (received_to_uri && ptr->received.s && ptr->received.len) { if (add_received(&new_uri, &ptr->c, &ptr->received) < 0) { ERR("branch: out of memory\n"); goto cont; /* try to continue */ } if (append_branch(msg, &new_uri, 0, 0, ptr->q, 0, 0) == -1) { ERR("Error while appending a branch\n"); pkg_free(new_uri.s); if (ser_error == E_TOO_MANY_BRANCHES) goto skip; else goto cont; /* try to continue, maybe we have an oversized contact */ } pkg_free(new_uri.s); /* append_branch doesn't free it */ } else { if (append_branch(msg, &ptr->c, &ptr->received, 0 /* path */, ptr->q, 0, ptr->sock) == -1) { ERR("Error while appending a branch\n"); goto skip; /* Return OK here so the function succeeds */ } } nat |= ptr->flags & FL_NAT; } cont: ptr = ptr->next; } skip: ul.unlock_udomain((udomain_t*)table); if (nat) setflag(msg, load_nat_flag); return 1; }
/* * Authorize digest credentials */ static inline int digest_authenticate(struct sip_msg* msg, fparam_t* realm, char* tname, hdr_types_t hftype) { char ha1[256]; int res; struct hdr_field* h; auth_body_t* cred; str domain, table; db1_res_t* result = NULL; int ret; cred = 0; ret = AUTH_ERROR; if(!tname) { LM_ERR("invalid table parameter\n"); return AUTH_ERROR; } table.s = tname; table.len = strlen(tname); if (get_str_fparam(&domain, msg, realm) < 0) { LM_ERR("failed to get realm value\n"); goto end; } if (domain.len==0) { LM_ERR("invalid realm parameter - empty value\n"); goto end; } LM_DBG("realm value [%.*s]\n", domain.len, domain.s); ret = auth_api.pre_auth(msg, &domain, hftype, &h, NULL); switch(ret) { case ERROR: case BAD_CREDENTIALS: LM_DBG("error or bad credentials\n"); ret = AUTH_ERROR; goto end; case CREATE_CHALLENGE: LM_ERR("CREATE_CHALLENGE is not a valid state\n"); ret = AUTH_ERROR; goto end; case DO_RESYNCHRONIZATION: LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n"); ret = AUTH_ERROR; goto end; case NOT_AUTHENTICATED: LM_DBG("not authenticated\n"); ret = AUTH_ERROR; goto end; case DO_AUTHENTICATION: break; case AUTHENTICATED: ret = AUTH_OK; goto end; } cred = (auth_body_t*)h->parsed; res = get_ha1(&cred->digest.username, &domain, &table, ha1, &result); if (res < 0) { /* Error while accessing the database */ ret = AUTH_ERROR; goto end; } if (res > 0) { /* Username not found in the database */ ret = AUTH_USER_UNKNOWN; goto end; } /* Recalculate response, it must be same to authorize successfully */ ret = auth_api.check_response(&(cred->digest), &msg->first_line.u.request.method, ha1); if(ret==AUTHENTICATED) { ret = AUTH_OK; switch(auth_api.post_auth(msg, h)) { case AUTHENTICATED: generate_avps(result); break; default: ret = AUTH_ERROR; break; } } else { if(ret==NOT_AUTHENTICATED) ret = AUTH_INVALID_PASSWORD; else ret = AUTH_ERROR; } end: if(result) auth_dbf.free_result(auth_db_handle, result); return ret; }
/** * @brief do WWW-Digest authentication with password taken from cfg var */ static int pv_authenticate(struct sip_msg *msg, char *p1, char *p2, char *p3, int hftype) { int flags = 0; str realm = {0, 0}; str passwd = {0, 0}; struct hdr_field* h; auth_body_t* cred; int ret; str hf = {0, 0}; avp_value_t val; static char ha1[256]; struct qp *qop = NULL; cred = 0; ret = AUTH_ERROR; if (get_str_fparam(&realm, msg, (fparam_t*)p1) < 0) { LM_ERR("failed to get realm value\n"); goto error; } if(realm.len==0) { LM_ERR("invalid realm value - empty content\n"); goto error; } if (get_str_fparam(&passwd, msg, (fparam_t*)p2) < 0) { LM_ERR("failed to get passwd value\n"); goto error; } if(passwd.len==0) { LM_ERR("invalid password value - empty content\n"); goto error; } if (get_int_fparam(&flags, msg, (fparam_t*)p3) < 0) { LM_ERR("invalid flags value\n"); goto error; } switch(pre_auth(msg, &realm, hftype, &h, NULL)) { case ERROR: case BAD_CREDENTIALS: LM_DBG("error or bad credentials\n"); ret = AUTH_ERROR; goto end; case CREATE_CHALLENGE: LM_ERR("CREATE_CHALLENGE is not a valid state\n"); ret = AUTH_ERROR; goto end; case DO_RESYNCHRONIZATION: LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n"); ret = AUTH_ERROR; goto end; case NOT_AUTHENTICATED: LM_DBG("not authenticated\n"); ret = AUTH_ERROR; goto end; case DO_AUTHENTICATION: break; case AUTHENTICATED: ret = AUTH_OK; goto end; } cred = (auth_body_t*)h->parsed; /* compute HA1 if needed */ if ((flags&1)==0) { /* Plaintext password is stored in PV, calculate HA1 */ calc_HA1(HA_MD5, &cred->digest.username.whole, &realm, &passwd, 0, 0, ha1); LM_DBG("HA1 string calculated: %s\n", ha1); } else { memcpy(ha1, passwd.s, passwd.len); ha1[passwd.len] = '\0'; } /* Recalculate response, it must be same to authorize successfully */ ret = auth_check_response(&(cred->digest), &msg->first_line.u.request.method, ha1); if(ret==AUTHENTICATED) { ret = AUTH_OK; switch(post_auth(msg, h)) { case AUTHENTICATED: break; default: ret = AUTH_ERROR; break; } } else { if(ret==NOT_AUTHENTICATED) ret = AUTH_INVALID_PASSWORD; else ret = AUTH_ERROR; } end: if (ret < 0) { /* check if required to add challenge header as avp */ if(!(flags&14)) return ret; if(flags&8) { qop = &auth_qauthint; } else if(flags&4) { qop = &auth_qauth; } if (get_challenge_hf(msg, (cred ? cred->stale : 0), &realm, NULL, NULL, qop, hftype, &hf) < 0) { ERR("Error while creating challenge\n"); ret = AUTH_ERROR; } else { val.s = hf; if(add_avp(challenge_avpid.flags | AVP_VAL_STR, challenge_avpid.name, val) < 0) { LM_ERR("Error while creating attribute with challenge\n"); ret = AUTH_ERROR; } pkg_free(hf.s); } } error: return ret; }