Beispiel #1
0
int save(struct sip_msg* _m, char* _d, char* _f, char* _s)
{
	struct sip_msg* msg = _m;
	struct cell* t = NULL;
	contact_t* _c;
	contact_t* reply_c = NULL;
	contact_t* request_c = NULL;
	int st;
	int ret;
	int requested_exp = 0;
	int enforced_exp = 0;
	int_str val;
	struct lump* l;
	char* p;
	char forced_binding_buf[MAX_FORCED_BINDING_LEN];
	str forced_binding = {NULL, 0};
	str *binding_uri;

	if(_m->first_line.type != SIP_REPLY)
		return save_aux(_m, NULL, _d, _f, _s);

	memset(&val, 0, sizeof(int_str));
	if(!tmb.t_gett) {
		LM_ERR("TM module not loaded - can not save on reply\n");
		return -1;
	}
	t = tmb.t_gett();
	if(!t || t==T_UNDEFINED) {
		LM_ERR("Transaction not created on Register - can not save on reply\n");
		return -1;
	}
	msg = t->uas.request;
	if(!msg) {
		LM_ERR("NULL request - can not save on reply\n");
		return -1;
	}

	if (parse_message(_m) < 0) return -1;
	if (check_contacts(_m, &st) > 0) return -1;
	if (parse_message(msg) < 0) return -1;
	if (check_contacts(msg, &st) > 0) return -1;

	/* msg - request
	   _m  - reply 
	*/
	request_c = get_first_contact(msg);
	if(request_c) {
		/* For now, we deal only with the first contact
		 * FIXME: implement multiple contact handling - see check_contacts() */
		if(!request_c->expires || !request_c->expires->body.len) {
			if (((exp_body_t*)(msg->expires->parsed))->valid) {
				requested_exp = ((exp_body_t*)(msg->expires->parsed))->val;
			} else {
				LM_WARN("No expired defined\n");
			}
		} else {
			if (str2int(&(request_c->expires->body), (unsigned int*)&requested_exp)<0) {
				LM_ERR("unable to get expires from [%.*s]\n",
					request_c->expires->body.len, request_c->expires->body.s);
				return -1;
			}
		}
		LM_DBG("Binding received from client [%.*s] with requested expires [%d]\n",
				request_c->uri.len, request_c->uri.s, requested_exp);

		/* We will use the Contact from request:
		 *  - check if a modified contact was set in avp */
		if (mct_avp_name >= 0 &&
			search_first_avp(mct_avp_type,mct_avp_name,&val,0)
			&& val.s.len > 0) {
			LM_DBG("Binding sent to upper registrar [%.*s]\n",
					val.s.len, val.s.s);
			binding_uri = &val.s;
		} else {
			binding_uri = &request_c->uri;
		}

		if (requested_exp) {
			/* Let's get the contact from reply */
			_c = get_first_contact(_m);
			while (_c) {
				if (compare_uris(binding_uri, NULL, &_c->uri, NULL) == 0) {
					if(_c->expires && _c->expires->body.len) {
						if(str2int(&(_c->expires->body),
							(unsigned int*)&enforced_exp)<0) {
							LM_ERR("unable to get expires from [%.*s]\n",
								_c->expires->body.len,
								_c->expires->body.s);
							return -1;
						}
						LM_DBG("Binding received from upper registrar"
							" [%.*s] with imposed expires [%d]\n",
							_c->uri.len, _c->uri.s, enforced_exp);
						reply_c = _c;
						forced_binding.len = request_c->uri.len + 11 +
									reply_c->expires->body.len;
						if (forced_binding.len <= MAX_FORCED_BINDING_LEN) {
							forced_binding.s = forced_binding_buf;
							forced_binding_buf[0] = '<';
							memcpy(&forced_binding_buf[1],
								request_c->uri.s,
								request_c->uri.len);
							memcpy(&forced_binding_buf[request_c->uri.len + 1],
								">;expires=", 10);
							memcpy(&forced_binding_buf[request_c->uri.len + 11],
								reply_c->expires->body.s,
								reply_c->expires->body.len);
							LM_DBG("forcing binding [%.*s]\n",
								forced_binding.len,
								forced_binding.s);
							break;
						} else {
							LM_ERR("forced binding to BIG:"
								" %d > MAX_FORCED_BINDING_LEN\n",
								forced_binding.len);
							return -1;
						}
					}
				} else {
					LM_DBG("Unmatched binding [%.*s]\n",
							_c->uri.len, _c->uri.s);
				}
				_c = get_next_contact(_c);
			}
		}
		ret = save_aux(msg, forced_binding.s?&forced_binding:NULL, _d, _f, _s);
	} else {
		LM_DBG("No Contact in request => this is an interogation\n");
		ret = 1;
	}


	/* if the contact was changed in register - put the modif value */
	if(request_c && requested_exp && val.s.s) {
		if(reply_c) {
			LM_DBG("replacing contact uri [%.*s] with [%.*s]\n",
				reply_c->uri.len, reply_c->uri.s,
				request_c->uri.len, request_c->uri.s);
			/* replace with what was received in Register */
			/* reply_c->uri - now contains the initial received value */
			if((l=del_lump(_m, reply_c->uri.s - _m->buf, reply_c->uri.len, 0))==0) {
				LM_ERR("Failed to delete contact uri lump\n");
				ret = -1;
				goto done;
			}
			p = pkg_malloc( request_c->uri.len);
			if (p==0) {
				LM_ERR("no more pkg mem\n");
				ret = -1;
				goto done;
			}
			memcpy( p, request_c->uri.s, request_c->uri.len );
			if (insert_new_lump_after( l, p, request_c->uri.len, 0)==0) {
				LM_ERR("insert new lump failed\n");
				pkg_free(p);
				ret =-1;
				goto done;
			}
		}
	}

done:
	clean_msg_clone(t->uas.request, t->uas.request, t->uas.end_request);

	return ret;
}
Beispiel #2
0
int dlg_validate_dialog( struct sip_msg* req, struct dlg_cell *dlg)
{
	struct dlg_leg *leg;
	unsigned int n,m;
	int nr_routes,i,src_leg;
	str *rr_uri,*route_uris;

	if (last_dst_leg<0 || last_dst_leg>=dlg->legs_no[DLG_LEGS_USED]) {
		log_bogus_dst_leg(dlg);
		LM_ERR("Script error - validate function before having a dialog\n");
		return -4;
	}

	leg = & dlg->legs[ last_dst_leg ];

	/* first check the cseq */
	if ( (!req->cseq && parse_headers(req,HDR_CSEQ_F,0)<0) || !req->cseq ||
	!req->cseq->parsed) {
		LM_ERR("bad sip message or missing CSeq hdr :-/\n");
		return -4;
	}

	n = m = 0;

	if (req->first_line.u.request.method_value == METHOD_ACK) {
		/* ACKs should have the same cseq as INVITEs */
		if (last_dst_leg == DLG_CALLER_LEG)
			src_leg = callee_idx(dlg);
		else
			src_leg = DLG_CALLER_LEG;

		if ( str2int( &((get_cseq(req))->number), &n)!=0 ||
		str2int( &(dlg->legs[src_leg].inv_cseq), &m)!=0 || n!=m ) {
			LM_DBG("cseq test for ACK falied recv=%d, old=%d\n",n,m);
			return -1;
		}
	} else {
		if ( str2int( &((get_cseq(req))->number), &n)!=0 ||
		str2int( &(leg->prev_cseq), &m)!=0 || n<=m ) {
			LM_DBG("cseq test falied recv=%d, old=%d\n",n,m);
			return -1;
		}
	}



	LM_DBG("CSEQ validation passed\n");

	/* because fix_routing was called on the request */
	if(dlg->flags & DLG_FLAG_TOPHIDING)
		return 0;

	if (dlg->state <= DLG_STATE_EARLY)
		return 0;

	if (leg->contact.len) {
		rr_uri = d_rrb.get_remote_target(req);
		if (rr_uri == NULL)
		{
			LM_ERR("failed fetching remote target from msg\n");
			return -4;
		}

		if (compare_uris(rr_uri,0,&leg->contact,0))
		{
			LM_ERR("failed to validate remote contact: dlg=[%.*s] , req=[%.*s]\n",
					leg->contact.len,leg->contact.s,rr_uri->len,rr_uri->s);
			return -2;
		}
	}

	LM_DBG("Remote contact succesfully validated\n");

	/* check the route set - is the the same as in original request */
	/* the route set (without the first Route) must be the same as the
	   one stored in the destination leg */
	/* extract the RR parts */

	if( parse_headers( req, HDR_EOH_F, 0)<0 ) {
		LM_ERR("failed to parse headers when looking after ROUTEs\n");
		return -4;
	}

	if ( req->route==NULL) {
		if ( leg->route_set.len!=0) {
			LM_DBG("route check failed (req has no route, but dialog has\n");
			return -3;
		}
	} else {
		route_uris = d_rrb.get_route_set(req,&nr_routes);
		if (route_uris == NULL) {
			LM_ERR("failed fetching route URIs from the msg\n");
			return -4;
		}

		if (nr_routes != leg->nr_uris) {
			LM_ERR("Different number of routes found in msg. req=%d, dlg=%d\n",
					nr_routes,leg->nr_uris);
			return -3;
		}

		for (i=0;i<nr_routes;i++)
		{
			LM_DBG("route %d. req=[%.*s],dlg=[%.*s]\n",
					i,route_uris[i].len,route_uris[i].s,leg->route_uris[i].len,
					leg->route_uris[i].s);
			if (compare_uris(&route_uris[i],0,&leg->route_uris[i],0))
			{
				LM_ERR("Check failed for route number %d. req=[%.*s],dlg=[%.*s]\n",
						i,route_uris[i].len,route_uris[i].s,leg->route_uris[i].len,
						leg->route_uris[i].s);
				return -3;
			}
		}
	}

	LM_DBG("Route Headers succesfully validated\n");

	return 0;
}