hdr_field_t* get_hdr(const sip_msg_t* const msg, const enum _hdr_types_t ht) { hdr_field_t *hdr; if (msg->parsed_flag & HDR_T2F(ht)) for(hdr = msg->headers; hdr; hdr = hdr->next) { if(hdr->type == ht) return hdr; } return NULL; }
/* note: it continues where it previously stopped and goes ahead until end is encountered or desired HFs are found; if you call it twice for the same HF which is present only once, it will fail the second time; if you call it twice and the HF is found on second time too, it's not replaced in the well-known HF pointer but just added to header list; if you want to use a dumb convenience function which will give you the first occurrence of a header you are interested in, look at check_transaction_quadruple */ int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int next) { struct hdr_field* hf; char* tmp; char* rest; char* end; hdr_flags_t orig_flag; end=msg->buf+msg->len; tmp=msg->unparsed; if (unlikely(next)) { orig_flag = msg->parsed_flag; msg->parsed_flag &= ~flags; } else orig_flag=0; #ifdef EXTRA_DEBUG DBG("parse_headers: flags=%llx\n", (unsigned long long)flags); #endif while( tmp<end && (flags & msg->parsed_flag) != flags) { prefetch_loc_r(tmp+64, 1); hf=pkg_malloc(sizeof(struct hdr_field)); if (unlikely(hf==0)) { ser_error=E_OUT_OF_MEM; LOG(L_ERR, "ERROR:parse_headers: memory allocation error\n"); goto error; } memset(hf,0, sizeof(struct hdr_field)); hf->type=HDR_ERROR_T; rest=get_hdr_field(tmp, end, hf); switch (hf->type) { case HDR_ERROR_T: LOG(L_INFO,"ERROR: bad header field [%.*s]\n", (end-tmp>20)?20:(int)(end-tmp), tmp); goto error; case HDR_EOH_T: msg->eoh=tmp; /* or rest?*/ msg->parsed_flag|=HDR_EOH_F; pkg_free(hf); goto skip; case HDR_ACCEPTCONTACT_T: case HDR_ALLOWEVENTS_T: case HDR_CONTENTENCODING_T: case HDR_REFERREDBY_T: case HDR_REJECTCONTACT_T: case HDR_REQUESTDISPOSITION_T: case HDR_WWW_AUTHENTICATE_T: case HDR_PROXY_AUTHENTICATE_T: case HDR_RETRY_AFTER_T: case HDR_OTHER_T: /* mark the type as found/parsed*/ msg->parsed_flag|=HDR_T2F(hf->type); break; case HDR_CALLID_T: if (msg->callid==0) msg->callid=hf; msg->parsed_flag|=HDR_CALLID_F; break; case HDR_SIPIFMATCH_T: if (msg->sipifmatch==0) msg->sipifmatch=hf; msg->parsed_flag|=HDR_SIPIFMATCH_F; break; case HDR_TO_T: if (msg->to==0) msg->to=hf; msg->parsed_flag|=HDR_TO_F; break; case HDR_CSEQ_T: if (msg->cseq==0) msg->cseq=hf; msg->parsed_flag|=HDR_CSEQ_F; break; case HDR_FROM_T: if (msg->from==0) msg->from=hf; msg->parsed_flag|=HDR_FROM_F; break; case HDR_CONTACT_T: if (msg->contact==0) msg->contact=hf; msg->parsed_flag|=HDR_CONTACT_F; break; case HDR_MAXFORWARDS_T: if(msg->maxforwards==0) msg->maxforwards=hf; msg->parsed_flag|=HDR_MAXFORWARDS_F; break; case HDR_ROUTE_T: if (msg->route==0) msg->route=hf; msg->parsed_flag|=HDR_ROUTE_F; break; case HDR_RECORDROUTE_T: if (msg->record_route==0) msg->record_route = hf; msg->parsed_flag|=HDR_RECORDROUTE_F; break; case HDR_CONTENTTYPE_T: if (msg->content_type==0) msg->content_type = hf; msg->parsed_flag|=HDR_CONTENTTYPE_F; break; case HDR_CONTENTLENGTH_T: if (msg->content_length==0) msg->content_length = hf; msg->parsed_flag|=HDR_CONTENTLENGTH_F; break; case HDR_AUTHORIZATION_T: if (msg->authorization==0) msg->authorization = hf; msg->parsed_flag|=HDR_AUTHORIZATION_F; break; case HDR_EXPIRES_T: if (msg->expires==0) msg->expires = hf; msg->parsed_flag|=HDR_EXPIRES_F; break; case HDR_PROXYAUTH_T: if (msg->proxy_auth==0) msg->proxy_auth = hf; msg->parsed_flag|=HDR_PROXYAUTH_F; break; case HDR_PROXYREQUIRE_T: if (msg->proxy_require==0) msg->proxy_require = hf; msg->parsed_flag|=HDR_PROXYREQUIRE_F; break; case HDR_SUPPORTED_T: if (msg->supported==0) msg->supported=hf; msg->parsed_flag|=HDR_SUPPORTED_F; break; case HDR_REQUIRE_T: if (msg->require==0) msg->require=hf; msg->parsed_flag|=HDR_REQUIRE_F; break; case HDR_UNSUPPORTED_T: if (msg->unsupported==0) msg->unsupported=hf; msg->parsed_flag|=HDR_UNSUPPORTED_F; break; case HDR_ALLOW_T: if (msg->allow==0) msg->allow = hf; msg->parsed_flag|=HDR_ALLOW_F; break; case HDR_EVENT_T: if (msg->event==0) msg->event = hf; msg->parsed_flag|=HDR_EVENT_F; break; case HDR_ACCEPT_T: if (msg->accept==0) msg->accept = hf; msg->parsed_flag|=HDR_ACCEPT_F; break; case HDR_ACCEPTLANGUAGE_T: if (msg->accept_language==0) msg->accept_language = hf; msg->parsed_flag|=HDR_ACCEPTLANGUAGE_F; break; case HDR_ORGANIZATION_T: if (msg->organization==0) msg->organization = hf; msg->parsed_flag|=HDR_ORGANIZATION_F; break; case HDR_PRIORITY_T: if (msg->priority==0) msg->priority = hf; msg->parsed_flag|=HDR_PRIORITY_F; break; case HDR_SUBJECT_T: if (msg->subject==0) msg->subject = hf; msg->parsed_flag|=HDR_SUBJECT_F; break; case HDR_USERAGENT_T: if (msg->user_agent==0) msg->user_agent = hf; msg->parsed_flag|=HDR_USERAGENT_F; break; case HDR_SERVER_T: if (msg->server==0) msg->server = hf; msg->parsed_flag|=HDR_SERVER_F; break; case HDR_CONTENTDISPOSITION_T: if (msg->content_disposition==0) msg->content_disposition = hf; msg->parsed_flag|=HDR_CONTENTDISPOSITION_F; break; case HDR_DIVERSION_T: if (msg->diversion==0) msg->diversion = hf; msg->parsed_flag|=HDR_DIVERSION_F; break; case HDR_RPID_T: if (msg->rpid==0) msg->rpid = hf; msg->parsed_flag|=HDR_RPID_F; break; case HDR_REFER_TO_T: if (msg->refer_to==0) msg->refer_to = hf; msg->parsed_flag|=HDR_REFER_TO_F; break; case HDR_SESSIONEXPIRES_T: if (msg->session_expires==0) msg->session_expires = hf; msg->parsed_flag|=HDR_SESSIONEXPIRES_F; break; case HDR_MIN_SE_T: if (msg->min_se==0) msg->min_se = hf; msg->parsed_flag|=HDR_MIN_SE_F; break; case HDR_SUBSCRIPTION_STATE_T: if (msg->subscription_state==0) msg->subscription_state = hf; msg->parsed_flag|=HDR_SUBSCRIPTION_STATE_F; break; case HDR_VIA_T: msg->parsed_flag|=HDR_VIA_F; DBG("parse_headers: Via found, flags=%llx\n", (unsigned long long)flags); if (msg->via1==0) { DBG("parse_headers: this is the first via\n"); msg->h_via1=hf; msg->via1=hf->parsed; if (msg->via1->next) { msg->via2=msg->via1->next; msg->parsed_flag|=HDR_VIA2_F; } } else if (msg->via2==0) { msg->h_via2=hf; msg->via2=hf->parsed; msg->parsed_flag|=HDR_VIA2_F; DBG("parse_headers: this is the second via\n"); } break; case HDR_DATE_T: if (msg->date==0) msg->date=hf; msg->parsed_flag|=HDR_DATE_F; break; case HDR_IDENTITY_T: if (msg->identity==0) msg->identity=hf; msg->parsed_flag|=HDR_IDENTITY_F; break; case HDR_IDENTITY_INFO_T: if (msg->identity_info==0) msg->identity_info=hf; msg->parsed_flag|=HDR_IDENTITY_INFO_F; break; case HDR_PATH_T: if (msg->path==0) msg->path=hf; msg->parsed_flag|=HDR_PATH_F; break; case HDR_PRIVACY_T: if (msg->privacy==0) msg->privacy=hf; msg->parsed_flag|=HDR_PRIVACY_F; break; case HDR_PAI_T: if (msg->pai==0) msg->pai=hf; msg->parsed_flag|=HDR_PAI_F; break; case HDR_PPI_T: if (msg->ppi==0) msg->ppi=hf; msg->parsed_flag|=HDR_PPI_F; break; case HDR_REASON_T: msg->parsed_flag|=HDR_REASON_F; break; default: LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n", hf->type); goto error; } /* add the header to the list*/ if (msg->last_header==0) { msg->headers=hf; msg->last_header=hf; } else { msg->last_header->next=hf; msg->last_header=hf; } #ifdef EXTRA_DEBUG DBG("header field type %d, name=<%.*s>, body=<%.*s>\n", hf->type, hf->name.len, ZSW(hf->name.s), hf->body.len, ZSW(hf->body.s)); #endif tmp=rest; } skip: msg->unparsed=tmp; /* restore original flags */ msg->parsed_flag |= orig_flag; return 0; error: ser_error=E_BAD_REQ; if (hf) pkg_free(hf); /* restore original flags */ msg->parsed_flag |= orig_flag; return -1; }
/** * Find credentials with given realm in a SIP message header. * @param _m - the SIP message to look into * @param _realm - the realm to match in the authorization header * @param _hftype - the header type (HDR_AUTHORIZATION_T,HDR_PROXYAUTH_T) * @param _h - header pointer to fill with the match * @returns 0 on success, 1 if not found * \note This function is taken from the auth module */ inline int find_credentials(struct sip_msg* _m, str* _realm, hdr_types_t _hftype, struct hdr_field** _h) { struct hdr_field** hook, *ptr, *prev; hdr_flags_t hdr_flags; int res; str* r; /* * Determine if we should use WWW-Authorization or * Proxy-Authorization header fields, this parameter * is set in www_authorize and proxy_authorize */ switch(_hftype) { case HDR_AUTHORIZATION_T: hook = &(_m->authorization); hdr_flags=HDR_AUTHORIZATION_F; break; case HDR_PROXYAUTH_T: hook = &(_m->proxy_auth); hdr_flags=HDR_PROXYAUTH_F; break; default: hook = &(_m->authorization); hdr_flags=HDR_T2F(_hftype); break; } /* * If the credentials haven't been parsed yet, do it now */ if (*hook == 0) { /* No credentials parsed yet */ if (parse_headers(_m, hdr_flags, 0) == -1) { LOG(L_ERR, "find_credentials(): Error while parsing headers\n"); return -1; } } ptr = *hook; /* * Iterate through the credentials in the message and * find credentials with given realm */ while(ptr) { res = parse_credentials(ptr); ptr->type = HDR_AUTHORIZATION_T; if (res < 0) { LOG(L_ERR, "find_credentials(): Error while parsing credentials\n"); return (res == -1) ? -2 : -3; } else if (res == 0) { if (_realm->len) { r = &(((auth_body_t*)(ptr->parsed))->digest.realm); if (r->len == _realm->len) { if (!strncasecmp(_realm->s, r->s, r->len)) { *_h = ptr; return 0; } } } else { *_h = ptr; return 0; } } prev = ptr; if (parse_headers(_m, hdr_flags, 1) == -1) { LOG(L_ERR, "find_credentials(): Error while parsing headers\n"); return -4; } else { if (prev != _m->last_header) { if (_m->last_header->type == _hftype) ptr = _m->last_header; else break; } else break; } } /* * Credentials with given realm not found */ return 1; }
/** * Find credentials with given realm in a SIP message header * without parsing the credentials - just find the right * authorize with stupid byte by byte comparison * Find credentials with given realm in a SIP message header. * @param _m - the SIP message to look into * @param realm - the realm to match in the authorization header * @param _hftype - the header type (HDR_AUTHORIZATION_T,HDR_PROXYAUTH_T) * @param _h - header pointer to fill with the match * @returns 0 on success, 1 if not found * \note This function is taken from the auth module */ inline int find_credentials_noparse(struct sip_msg* _m, str* realm, hdr_types_t _hftype, struct hdr_field** _h) { struct hdr_field** hook, *ptr, *prev; hdr_flags_t hdr_flags; int i,k; /* * Determine if we should use WWW-Authorization or * Proxy-Authorization header fields, this parameter * is set in www_authorize and proxy_authorize */ switch(_hftype) { case HDR_AUTHORIZATION_T: hook = &(_m->authorization); hdr_flags=HDR_AUTHORIZATION_F; break; case HDR_PROXYAUTH_T: hook = &(_m->proxy_auth); hdr_flags=HDR_PROXYAUTH_F; break; default: hook = &(_m->authorization); hdr_flags=HDR_T2F(_hftype); break; } /* * If the credentials haven't been parsed yet, do it now */ if (*hook == 0) { /* No credentials parsed yet */ if (parse_headers(_m, hdr_flags, 0) == -1) { LOG(L_ERR, "find_credentials(): Error while parsing headers\n"); return -1; } } ptr = *hook; /* * Iterate through the credentials in the message and * find credentials with given realm */ while(ptr) { k = ptr->body.len - realm_par.len - realm->len; for(i=0;i<k;i++) if (strncasecmp(ptr->body.s+i,realm_par.s,realm_par.len)==0){ if (strncasecmp(ptr->body.s+i+realm_par.len,realm->s,realm->len)==0){ *_h = ptr; return 0; } else break; } prev = ptr; if (parse_headers(_m, hdr_flags, 1) == -1) { LOG(L_ERR, "find_credentials(): Error while parsing headers\n"); return -4; } else { if (prev != _m->last_header) { if (_m->last_header->type == _hftype) ptr = _m->last_header; else break; } else break; } } /* * Credentials with given realm not found */ return 1; }
/* * Find credentials with given realm in a SIP message header */ int find_credentials(struct sip_msg* msg, str* realm, hdr_types_t hftype, struct hdr_field** hdr) { struct hdr_field** hook, *ptr; hdr_flags_t hdr_flags; int res; str* r; /* * Determine if we should use WWW-Authorization or * Proxy-Authorization header fields, this parameter * is set in www_authorize and proxy_authorize */ switch(hftype) { case HDR_AUTHORIZATION_T: hook = &(msg->authorization); hdr_flags=HDR_AUTHORIZATION_F; break; case HDR_PROXYAUTH_T: hook = &(msg->proxy_auth); hdr_flags=HDR_PROXYAUTH_F; break; default: hook = &(msg->authorization); hdr_flags=HDR_T2F(hftype); break; } /* * If the credentials haven't been parsed yet, do it now */ if (*hook == 0) { /* No credentials parsed yet */ if (parse_headers(msg, hdr_flags, 0) == -1) { LM_ERR("error while parsing headers\n"); return -1; } } ptr = *hook; /* * Iterate through the credentials in the message and * find credentials with given realm */ while(ptr) { res = parse_credentials(ptr); if (res < 0) { LM_ERR("error while parsing credentials\n"); return (res == -1) ? -2 : -3; } else if (res == 0) { r = &(((auth_body_t*)(ptr->parsed))->digest.realm); if (r->len == realm->len) { if (!strncasecmp(realm->s, r->s, r->len)) { *hdr = ptr; return 0; } } } if (parse_headers(msg, hdr_flags, 1) == -1) { LM_ERR("error while parsing headers\n"); return -4; } else { ptr = next_sibling_hdr(ptr); if (!ptr) break; } } /* * Credentials with given realm not found */ return 1; }
/* Find credentials with given realm in a SIP message header */ int find_credentials(struct sip_msg* _m, str* _realm, int _hftype, struct hdr_field** _h) { struct hdr_field** hook, *ptr, *prev; int res; hdr_flags_t hdr_flags; str* r; switch(_hftype) { case HDR_AUTHORIZATION_T: hook = &(_m->authorization); hdr_flags=HDR_AUTHORIZATION_F; break; case HDR_PROXYAUTH_T: hook = &(_m->proxy_auth); hdr_flags=HDR_PROXYAUTH_F; break; default: hook = &(_m->authorization); hdr_flags=HDR_T2F(_hftype); break; } /* If the credentials haven't been parsed yet, do it now */ if (*hook == 0) if (parse_headers(_m, hdr_flags, 0) == -1) { LM_ERR("failed to parse headers\n"); return -1; } ptr = *hook; /* Iterate through the credentials of the message to find credentials with given realm */ while(ptr) { res = parse_credentials(ptr); if (res < 0) { LM_ERR("failed to parse credentials\n"); return (res == -1) ? -2 : -3; } else if (res == 0) { r = &(((auth_body_t*)(ptr->parsed))->digest.realm); if (r->len == _realm->len) { if (!strncasecmp(_realm->s, r->s, r->len)) { *_h = ptr; return 0; } } } prev = ptr; if (parse_headers(_m, hdr_flags, 1) == -1) { LM_ERR("failed to parse headers\n"); return -4; } else { if (prev != _m->last_header) { if (_m->last_header->type == _hftype) ptr = _m->last_header; else break; } else break; } } /* Credentials with given realm not found */ return 1; }
/** * Strips the "<strip_top_vias>" topmost via headers. * Leaves only the topmost "<allow_top_routes>" Record-Route headers. * */ int extract_allowed_headers(struct sip_msg *my_msg,int strip_top_vias,int allow_top_Rroutes,hdr_flags_t forbidden_hdrs,char *headers,int headers_len) { struct hdr_field *hf; rr_t *rb; struct via_body *vb; int len,k,rtcnt,i; len=0; rtcnt=allow_top_Rroutes; rb=NULL; vb=NULL; for(hf=my_msg->headers;hf;hf=hf->next){ if(forbidden_hdrs & HDR_T2F(hf->type)){ LM_DBG("Skipping header (%.*s)\n",hf->name.len,hf->name.s); continue; }else if(hf->type==HDR_VIA_T && strip_top_vias > 0){ /** All vias MUST be parsed !!*/ for(i=0,vb=hf->parsed;vb;vb=vb->next,i++); if(i<=strip_top_vias){ LM_DBG("Stripping vias [%.*s]\n",hf->len,hf->name.s); /** skip this via header*/ strip_top_vias-=i; }else{ assert(i>1); vb=hf->parsed; while(strip_top_vias--) vb=vb->next; k= (hf->name.s + hf->len) - vb->name.s; LM_DBG("Stripping vias [%.*s]\n",(int)(vb->name.s-hf->name.s), hf->name.s); if(k+VIA_LEN<headers_len){ memcpy(headers+len,VIA,VIA_LEN); len+=VIA_LEN; memcpy(headers+len,vb->name.s,k); len+=k; }else{ LM_ERR("Out Of Space !!\n"); goto error; } } }else if(hf->type==HDR_RECORDROUTE_T && rtcnt>=0){ if(rtcnt==0) continue; if(!hf->parsed && 0>parse_rr(hf)){ LM_ERR("parsing Record-Route:\"%.*s\"\n",hf->body.len,hf->body.s); goto error; } for(i=0,rb=hf->parsed;rb;rb=rb->next,i++); if(i<=rtcnt){ if((len+hf->len)<headers_len){ LM_DBG("Allowing RecordRoute [%.*s]\n",hf->len,hf->name.s); memcpy(headers+len,hf->name.s,hf->len); len+=hf->len; }else{ LM_ERR("Unable to keep recordroute (not enough space left in headers) Discarding \"%.*s\" \n",hf->name.len,hf->name.s); goto error; } /** is this dangerous ? because the rtcnt is the control variable for this conditional 'if' * so if I change rtcnt value in one of the statements... what then ??? */ rtcnt-=i; }else{ assert(rtcnt>0); rb=hf->parsed; while(--rtcnt) rb=rb->next; k= (((rb->nameaddr.name.s) + rb->len)-hf->name.s) ; if(len+k+CRLF_LEN<headers_len){ memcpy(headers+len,hf->name.s,k); LM_DBG("Allowing RecordRoute [%.*s\r\n]\n",k,hf->name.s); len+=k; memcpy(headers+len,CRLF,CRLF_LEN); len+=CRLF_LEN; }else{ LM_ERR("Out Of Space !!\n"); goto error; } } if(hf->parsed){ free_rr((rr_t **)(void*)(&hf->parsed)); hf->parsed=NULL; } }else{ if((len+hf->len)<headers_len){ memcpy(headers+len,hf->name.s,hf->len); len+=hf->len; }else{ LM_WARN("Too many headers. Discarding \"%.*s\" \n", hf->name.len,hf->name.s); } } }/*for*/ return len; error: return -1; }