/* * Return parsed To or From, host part of the parsed uri is realm */ int get_realm(struct sip_msg* _m, hdr_types_t _hftype, struct sip_uri** _u) { if(_u==NULL) return -1; if ((REQ_LINE(_m).method.len == 8) && !memcmp(REQ_LINE(_m).method.s, "REGISTER", 8) && (_hftype == HDR_AUTHORIZATION_T) ) { if (!_m->to && ((parse_headers(_m, HDR_TO_F, 0)==-1) || (!_m->to))) { LM_ERR("failed to parse TO headers\n"); return -1; } /* Body of To header field is parsed automatically */ if((*_u = parse_to_uri(_m))==NULL) return -1; } else { if (parse_from_header(_m) < 0) { LM_ERR("failed to parse FROM headers\n"); return -2; } if((*_u = parse_from_uri(_m))==NULL) return -1; } return 0; }
static int l_sipwatch_getFlag(lua_State *L) { struct sipapi_object *o; struct sip_uri *myuri; o = luaL_checkudata(L, 1, "siplua.api"); myuri = parse_from_uri(o->msg); if (myuri) { if (sipwatch_getFlagFromExtension(myuri->user.s, myuri->user.len)) { lua_pushboolean(L, 1); return 1; } } myuri = parse_to_uri(o->msg); if (myuri) { if (sipwatch_getFlagFromExtension(myuri->user.s, myuri->user.len)) { lua_pushboolean(L, 1); return 1; } } lua_pushnil(L); return 1; }
/* * Check username part in To header field */ int check_to(struct sip_msg* _m, char* _s1, char* _s2) { if (!_m->to && ((parse_headers(_m, HDR_TO_F, 0) == -1) || (!_m->to))) { LM_ERR("Error while parsing To header field\n"); return ERR_INTERNAL; } if(parse_to_uri(_m)==NULL) { LM_ERR("Error while parsing To header URI\n"); return ERR_INTERNAL; } return check_username(_m, &get_to(_m)->parsed_uri); }
static inline int check_to(struct sip_msg *_m, str *_username) { if (!_m->to && ((parse_headers(_m, HDR_TO_F, 0) == -1) || (!_m->to))) { LM_ERR("parsing To: header\n"); return CHECK_ERROR; } if (parse_to_uri(_m) == NULL) { LM_ERR("parsing To: URI\n"); return CHECK_ERROR; } return check_username(_username, &get_to(_m)->parsed_uri); }
static int l_siplua_getURI_User(lua_State *L) { struct sipapi_object *o; struct sip_uri *myuri; o = luaL_checkudata(L, 1, "siplua.api"); myuri = parse_to_uri(o->msg); if (!myuri) { /* siplua_log(L_WARN, "parse_to_uri returned NULL results"); */ lua_pushnil(L); } else { /* siplua_log(L_DBG, "parse_to_uri returned non-empty results"); */ lua_pushlstring(L, myuri->user.s, myuri->user.len); } return 1; }
/*! \brief * This function will process request that * contained some contact header fields */ static inline int add_contacts(struct sip_msg* _m, udomain_t* _d, str* _a, int _mode, int _use_regid) { int res; int ret; urecord_t* r; sip_uri_t *u; u = parse_to_uri(_m); if(u==NULL) return -2; ret = 0; ul.lock_udomain(_d, _a); res = ul.get_urecord(_d, _a, &r); if (res < 0) { rerrno = R_UL_GET_R; LM_ERR("failed to retrieve record from usrloc\n"); ul.unlock_udomain(_d, _a); return -2; } if (res == 0) { /* Contacts found */ if ((ret=update_contacts(_m, r, _mode, _use_regid)) < 0) { build_contact(_m, r->contacts, &u->host); ul.release_urecord(r); ul.unlock_udomain(_d, _a); return -3; } build_contact(_m, r->contacts, &u->host); ul.release_urecord(r); } else { if (insert_contacts(_m, _d, _a, _use_regid) < 0) { ul.unlock_udomain(_d, _a); return -4; } ret = 1; } ul.unlock_udomain(_d, _a); return ret; }
/* * Extract URI depending on the request from To or From header */ static inline int get_uri_user(struct sip_msg* _m, str** _uri_user) { struct sip_uri *puri; if ((REQ_LINE(_m).method.len == 8) && (memcmp(REQ_LINE(_m).method.s, "REGISTER", 8) == 0)) { if ((puri=parse_to_uri(_m))==NULL) { LM_ERR("failed to parse To header\n"); return -1; } } else { if ((puri=parse_from_uri(_m))==NULL) { LM_ERR("parsing From header\n"); return -1; } } *_uri_user = &(puri->user); return 0; }
int unregister(struct sip_msg* _m, udomain_t* _d, str* _uri) { str aor = {0, 0}; sip_uri_t *u; u = parse_to_uri(_m); if(u==NULL) return -2; if (extract_aor(_uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); return -1; } if (star(_m, _d, &aor, &u->host) < 0) { LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s); return -1; } return 1; }
/* * 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 && (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; }
int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri) { contact_t* c; int st, mode; str aor; int ret; sip_uri_t *u; rr_t *route; struct sip_uri puri; param_hooks_t hooks; param_t *params; contact_t *contact; int use_ob = 1, use_regid = 1; u = parse_to_uri(_m); if(u==NULL) goto error; rerrno = R_FINE; ret = 1; if (parse_message(_m) < 0) { goto error; } if (check_contacts(_m, &st) > 0) { goto error; } if (parse_supported(_m) == 0) { if (!(get_supported(_m) & F_OPTION_TAG_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_REQUIRE) { LM_WARN("Outbound required by server and not supported by UAC\n"); rerrno = R_OB_UNSUP; goto error; } } if (parse_require(_m) == 0) { if ((get_require(_m) & F_OPTION_TAG_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_NONE) { LM_WARN("Outbound required by UAC and not supported by server\n"); rerrno = R_OB_REQD; goto error; } } if (reg_outbound_mode != REG_OUTBOUND_NONE && _m->contact && _m->contact->parsed && !(parse_headers(_m, HDR_VIA2_F, 0) == -1 || _m->via2 == 0 || _m->via2->error != PARSE_OK)) { /* Outbound supported on server, and more than one Via: - not the first hop */ if (!(parse_headers(_m, HDR_PATH_F, 0) == -1 || _m->path == 0)) { route = (rr_t *)0; if (parse_rr_body(_m->path->body.s, _m->path->body.len, &route) < 0) { LM_ERR("Failed to parse Path: header body\n"); goto error; } if (parse_uri(route->nameaddr.uri.s, route->nameaddr.uri.len, &puri) < 0) { LM_ERR("Failed to parse Path: URI\n"); goto error; } if (parse_params(&puri.params, CLASS_URI, &hooks, ¶ms) != 0) { LM_ERR("Failed to parse Path: URI parameters\n"); goto error; } if (!hooks.uri.ob) { /* No ;ob parameter to top Path: URI - no outbound */ use_ob = 0; } } else { /* No Path: header - no outbound */ use_ob = 0; } contact = ((contact_body_t *) _m->contact->parsed)->contacts; if (!contact) { LM_ERR("empty Contact:\n"); goto error; } if ((use_ob == 0) && (reg_regid_mode == REG_REGID_OUTBOUND)) { if ((get_supported(_m) & F_OPTION_TAG_OUTBOUND) && contact->reg_id) { LM_WARN("Outbound used by UAC but not supported by edge proxy\n"); rerrno = R_OB_UNSUP_EDGE; goto error; } else { /* ignore ;reg-id parameter */ use_regid = 0; } } } get_act_time(); c = get_first_contact(_m); if (extract_aor((_uri)?_uri:&get_to(_m)->uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); goto error; } mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE; if (c == 0) { if (st) { if (star(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error; else ret=3; } else { if (no_contacts(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error; else ret=4; } } else { mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0; if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode, use_regid)) < 0) goto error; ret = (ret==0)?1:ret; } update_stat(accepted_registrations, 1); /* Only send reply upon request, not upon reply */ if ((is_route_type(REQUEST_ROUTE) || is_route_type(FAILURE_ROUTE)) && !is_cflag_set(REG_SAVE_NORPL_FL) && (reg_send_reply(_m) < 0)) return -1; return ret; error: update_stat(rejected_registrations, 1); if (is_route_type(REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) ) reg_send_reply(_m); return 0; }
int save(struct sip_msg* _m, udomain_t* _d, int _cflags, str *_uri) { contact_t* c; int st, mode; str aor; int ret; sip_uri_t *u; u = parse_to_uri(_m); if(u==NULL) goto error; rerrno = R_FINE; ret = 1; if (parse_message(_m) < 0) { goto error; } if (check_contacts(_m, &st) > 0) { goto error; } if (parse_supported(_m) == 0) { if (!(((struct supported_body *)_m->supported->parsed)->supported_all & F_SUPPORTED_OUTBOUND) && reg_outbound_mode == REG_OUTBOUND_REQUIRE) { LM_WARN("Outbound required by server and not supported by UAC\n"); rerrno = R_OB_UNSUP; goto error; } } get_act_time(); c = get_first_contact(_m); if (extract_aor((_uri)?_uri:&get_to(_m)->uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); goto error; } mem_only = is_cflag_set(REG_SAVE_MEM_FL)?FL_MEM:FL_NONE; if (c == 0) { if (st) { if (star(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error; else ret=3; } else { if (no_contacts(_m, (udomain_t*)_d, &aor, &u->host) < 0) goto error; else ret=4; } } else { mode = is_cflag_set(REG_SAVE_REPL_FL)?1:0; if ((ret=add_contacts(_m, (udomain_t*)_d, &aor, mode)) < 0) goto error; ret = (ret==0)?1:ret; } update_stat(accepted_registrations, 1); /* Only send reply upon request, not upon reply */ if ((is_route_type(REQUEST_ROUTE)) && !is_cflag_set(REG_SAVE_NORPL_FL) && (reg_send_reply(_m) < 0)) return -1; return ret; error: update_stat(rejected_registrations, 1); if (is_route_type(REQUEST_ROUTE) && !is_cflag_set(REG_SAVE_NORPL_FL) ) reg_send_reply(_m); return 0; }
/*! \brief * Message contained some contacts, but record with same address * of record was not found so we have to create a new record * and insert all contacts from the message that have expires * > 0 */ static inline int insert_contacts(struct sip_msg* _m, udomain_t* _d, str* _a, int _use_regid) { ucontact_info_t* ci; urecord_t* r = NULL; ucontact_t* c; contact_t* _c; unsigned int flags; int num, expires; int maxc; #ifdef USE_TCP int e_max, tcp_check; struct sip_uri uri; #endif sip_uri_t *u; u = parse_to_uri(_m); if(u==NULL) goto error; flags = mem_only; #ifdef USE_TCP if ( (_m->flags&tcp_persistent_flag) && (_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS ||_m->rcv.proto==PROTO_WS||_m->rcv.proto==PROTO_WSS)) { e_max = 0; tcp_check = 1; } else { e_max = tcp_check = 0; } #endif _c = get_first_contact(_m); maxc = reg_get_crt_max_contacts(); for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) { /* calculate expires */ calc_contact_expires(_m, _c->expires, &expires); /* Skip contacts with zero expires */ if (expires == 0) continue; if (maxc > 0 && num >= maxc) { LM_INFO("too many contacts (%d) for AOR <%.*s>\n", num, _a->len, _a->s); rerrno = R_TOO_MANY; goto error; } num++; if (r==0) { if (ul.insert_urecord(_d, _a, &r) < 0) { rerrno = R_UL_NEW_R; LM_ERR("failed to insert new record structure\n"); goto error; } } /* pack the contact_info */ if ( (ci=pack_ci( (ci==0)?_m:0, _c, expires, flags, _use_regid))==0 ) { LM_ERR("failed to extract contact info\n"); goto error; } /* hack to work with buggy clients having many contacts with same * address in one REGISTER - increase CSeq to detect if there was * one already added, then update */ ci->cseq++; if ( r->contacts==0 || ul.get_ucontact_by_instance(r, &_c->uri, ci, &c) != 0) { ci->cseq--; if (ul.insert_ucontact( r, &_c->uri, ci, &c) < 0) { rerrno = R_UL_INS_C; LM_ERR("failed to insert contact\n"); goto error; } } else { ci->cseq--; if (ul.update_ucontact( r, c, ci) < 0) { rerrno = R_UL_UPD_C; LM_ERR("failed to update contact\n"); goto error; } } #ifdef USE_TCP if (tcp_check) { /* parse contact uri to see if transport is TCP */ if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) { LM_ERR("failed to parse contact <%.*s>\n", _c->uri.len, _c->uri.s); } else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS || uri.proto==PROTO_WS || uri.proto==PROTO_WSS) { if (e_max) { LM_WARN("multiple TCP contacts on single REGISTER\n"); if (expires>e_max) e_max = expires; } else { e_max = expires; } } } #endif } if (r) { if (r->contacts) build_contact(_m, r->contacts, &u->host); ul.release_urecord(r); } else { /* No contacts found */ build_contact(_m, NULL, &u->host); } #ifdef USE_TCP if ( tcp_check && e_max>0 ) { e_max -= act_time; /*FIXME: Do we want this in the sr core?*/ /*force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );*/ } #endif return 0; error: if (r) ul.delete_urecord(_d, _a, r); return -1; }
int unregister(struct sip_msg* _m, udomain_t* _d, str* _uri, str *_ruid) { str aor = {0, 0}; sip_uri_t *u; urecord_t *r; ucontact_t *c; int res; if (_ruid == NULL) { /* No ruid provided - remove all contacts for aor */ if (extract_aor(_uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); return -1; } u = parse_to_uri(_m); if(u==NULL) return -2; if (star(_m, _d, &aor, &u->host) < 0) { LM_ERR("error unregistering user [%.*s]\n", aor.len, aor.s); return -1; } } else { /* ruid provided - remove a specific contact */ if (_uri->len > 0) { if (extract_aor(_uri, &aor, NULL) < 0) { LM_ERR("failed to extract Address Of Record\n"); return -1; } if (ul.get_urecord_by_ruid(_d, ul.get_aorhash(&aor), _ruid, &r, &c) != 0) { LM_WARN("AOR/Contact not found\n"); return -1; } if (ul.delete_ucontact(r, c) != 0) { ul.unlock_udomain(_d, &aor); LM_WARN("could not delete contact\n"); return -1; } ul.unlock_udomain(_d, &aor); } else { res = ul.delete_urecord_by_ruid(_d, _ruid); switch (res) { case -1: LM_ERR("could not delete contact\n"); return -1; case -2: LM_WARN("contact not found\n"); return -1; default: return 1; } } } return 1; }
/* * Authenticate using WWW/Proxy-Authorize header field */ int auth_check(struct sip_msg* _m, char* _realm, char* _table, char *_flags) { 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; if ((_m->REQ_METHOD == METHOD_ACK) || (_m->REQ_METHOD == METHOD_CANCEL)) { return AUTH_OK; } if(_m==NULL || _realm==NULL || _table==NULL || _flags==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 (get_str_fparam(&stable, _m, (fparam_t*)_table) < 0) { LM_ERR("failed to get realm value\n"); return AUTH_ERROR; } if (stable.len==0) { LM_ERR("invalid table parameter - empty value\n"); return AUTH_ERROR; } if(fixup_get_ivalue(_m, (gparam_p)_flags, &iflags)!=0) { LM_ERR("invalid flags parameter\n"); return -1; } 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)) { srealm = ((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(srealm.len!=uri->user.len || strncmp(srealm.s, uri->user.s, srealm.len)!=0) 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) 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)) 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) 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)) return AUTH_USER_MISMATCH; } } return AUTH_OK; } return ret; }
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; }
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; }
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; }
/*! * \brief Extract the username and domain from the SIP message * * Set the username and domain depending on the value of the SIP * message and the group check structure. * \param msg SIP message * \param gcp group check structure * \param username stored username * \param domain stored domain * \return 0 on success, -1 on failure */ 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; 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; default: { LM_ERR("incorrect check id %d\n", gcp->id); return -1; } } if (gcp->id != 4) { *username = turi->user; *domain = turi->host; } else { *username = c->digest.username.user; *domain = *(GET_REALM(&c->digest)); } return 0; }
int get_username_domain(struct sip_msg *msg, str *hf_s, str *username, str *domain) { struct sip_uri puri; struct sip_uri *turi; struct hdr_field* h; struct auth_body* c = 0; /* Makes gcc happy */ turi = NULL; switch( hf_type(hf_s) ) { 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; default: /* string */ if (parse_uri(hf_s->s, hf_s->len, &puri) < 0) { LM_ERR("failed to parse URI <%.*s>\n",hf_s->len, hf_s->s); return -1; } turi = &puri; break; } if ( c==NULL ) { *username = turi->user; *domain = turi->host; } else { *username = c->digest.username.user; *domain = *(GET_REALM(&c->digest)); } return 0; }