Esempio n. 1
0
/**
 * Looks for the UE Via in First Via header if its a request
 * or in the last if its a response and returns its body
 * @param msg - the SIP message
 * @returns the via of the UE
 */
struct via_body* cscf_get_ue_via(struct sip_msg *msg)
{
	struct via_body *vb=0;

	if (msg->first_line.type==SIP_REQUEST) vb = cscf_get_first_via(msg,0);
	else vb = cscf_get_last_via(msg);

	if (!vb) return 0;

	if (vb->port == 0) vb->port=5060;
	return vb;	
}
Esempio n. 2
0
/**
 * Process the REGISTER and verify Client-Security.
 * @param req - Register request
 * @param str1 - not used
 * @param str2 - not used
 * @returns 1 if ok, 0 if not
 */
int P_verify_security(struct sip_msg *req,char *str1, char *str2)
{
	str sec_hdr;
	struct hdr_field *h;
	struct via_body *vb;
	r_contact *c;
	r_security *s;
	r_security_type sec_type;
	float sec_q;
	
	str ealg,alg,tmp;
	unsigned int spi_pc,spi_ps;;
	int port_pc,port_ps;

	vb = cscf_get_first_via(req,&h);

	LOG(L_INFO,"DBG:"M_NAME":P_verify_security: Looking for <%d://%.*s:%d> \n",	vb->proto,vb->host.len,vb->host.s,vb->port);

	c = get_r_contact(vb->host,vb->port,vb->proto);

	r_act_time();
	if (!c){
		//first register
		LOG(L_DBG,"DBG:"M_NAME":P_verify_security: No Contact found ! \n");
		return CSCF_RETURN_TRUE;
	}

	if (!r_valid_contact(c) || !c->security_temp){
		LOG(L_DBG,"DBG:"M_NAME":P_verify_security: No security temp !.\n");
		r_unlock(c->hash);
		return CSCF_RETURN_TRUE;
	}

	sec_hdr = cscf_get_pref_security_header(req,s_security_verify, &sec_type,&sec_q);
	if (!sec_hdr.len)
	{	
		LOG(L_DBG,"DBG:"M_NAME":P_verify_security: No Security-Verify header found.\n");
		r_unlock(c->hash);
		return CSCF_RETURN_TRUE;
	}
	
	s = c->security_temp;
	
	switch (s->type)
	{
	case SEC_NONE:
		break;
	case SEC_TLS:
		if (sec_type != SEC_TLS || req->rcv.dst_port != pcscf_tls_port)
					goto error;
		break;
	case SEC_IPSEC:
		if (sec_type != SEC_IPSEC || req->rcv.dst_port != pcscf_ipsec_port_s)
		{
			LOG(L_INFO,"DBG:"M_NAME":P_verify_security: Not IPSEC tunnel!.\n");
			r_unlock(c->hash);
			goto error;
		}
		get_param(sec_hdr,s_ealg,ealg);
		get_param(sec_hdr,s_alg,alg);
		/* and for spis */
		get_param(sec_hdr,s_spi_c,tmp);
		strtoint(tmp,spi_pc);
		get_param(sec_hdr,s_spi_s,tmp);
		strtoint(tmp,spi_ps);
		/* and for ports */
		get_param(sec_hdr,s_port_c,tmp);
		strtoint(tmp,port_pc);
		get_param(sec_hdr,s_port_s,tmp);
		strtoint(tmp,port_ps);
		if ((s->data.ipsec->r_ealg.len != ealg.len || strncasecmp(s->data.ipsec->r_ealg.s, ealg.s, ealg.len)) ||
				(s->data.ipsec->r_alg.len != alg.len || strncasecmp(s->data.ipsec->r_alg.s, alg.s, alg.len)) || 
				(s->data.ipsec->spi_pc != spi_pc) ||
				(s->data.ipsec->spi_ps != spi_ps) ||
				(pcscf_ipsec_port_c != port_pc) ||
				(pcscf_ipsec_port_s != port_ps))
		{		
			LOG(L_INFO,"DBG:"M_NAME":P_verify_security: No valid Security-Verify header!.\n");
			r_unlock(c->hash);
			goto error;
		}
		break;
	}
	r_unlock(c->hash);
	
	return CSCF_RETURN_TRUE;
error:	
	return CSCF_RETURN_FALSE;
}
Esempio n. 3
0
/**
 * Process the 200 response for REGISTER and creates the first Security-Associations.
 * The rest of the SA are not set.
 * could come over that one. 
 * @param rpl - the 200 response
 * @param str1 - not used
 * @param str2 - not used
 * @returns 1 if ok, 0 if not
 */
int P_security_200(struct sip_msg *rpl,char *str1, char *str2)
{
	struct sip_msg *req;
	str sec_hdr;
	r_security_type sec_type;
	float sec_q;
	struct hdr_field *h;
	struct via_body *vb;
	r_contact *c;
	r_ipsec *i;
	int expires;
	unsigned long s_hash;
	char out_rpl[256],out_req[256],inc_rpl[256];

	if (!pcscf_use_ipsec &&!pcscf_use_tls) goto	ret_false;

	req = cscf_get_request_from_reply(rpl);
	if (!req){
		LOG(L_ERR,"ERR:"M_NAME":P_security_200: No transactional request found.\n");
		goto error;
	}	

	sec_hdr = cscf_get_pref_security_header(req,s_security_client, &sec_type,&sec_q);	
	if (!sec_hdr.len) {	
		LOG(L_DBG,"DBG:"M_NAME":P_security_200: No Security-Verify header found.\n");
		goto error;
	}
	
	/* find the expires (reg or dereg?) */
	expires = cscf_get_max_expires(req);
	
	/* get the IPSec info from the registrar */
	
	vb = cscf_get_first_via(req,&h);	
	LOG(L_DBG,"DBG:"M_NAME":P_security_200: Looking for <%d://%.*s:%d> \n",
		vb->proto,vb->host.len,vb->host.s,vb->port);

	c = get_r_contact(vb->host,vb->port,vb->proto);
		
	r_act_time();
	if (!c){
		LOG(L_ERR,"ERR:"M_NAME":P_security_200: Contact not found\n");		
		goto error;
	}
	
	if (c->security_temp){
		if (c->security && c->security->type == SEC_TLS && 
				(c->security->data.tls && c->security->data.tls->port_tls==req->rcv.src_port&& 
				 c->security->data.tls->session_hash!=0 && c->security->data.tls->session_hash == tls_get_session_hash(req))){
			/* don't replace security when doing an integrity protected REGISTER with
			 *  possible attack-garbage from security_temp */
			P_security_drop(c,c->security_temp);
			free_r_security(c->security_temp);
			c->security_temp = 0;
		}
		else
		{	
			if (c->security) {
				P_security_drop(c,c->security);
				free_r_security(c->security);
			}
			
			c->security = c->security_temp;
			c->security_temp = 0;
		}
	}	
	
	switch(sec_type){
		case SEC_NONE:
			break;
		case SEC_TLS:
			if (c->security && pcscf_use_tls) {
				r_tls *tls;
				int port_tls = req->rcv.src_port;
				s_hash = get_tls_session_hash(req);
				if (!s_hash){
					LOG(L_ERR,"ERR:"M_NAME":P_security_200: Session Hash could not be obtained !\n");
					r_unlock(c->hash);
					goto error;
				}	
				tls = new_r_tls(port_tls, s_hash);
				if (!tls) goto error;
				c->security->data.tls = tls;
			} 		
			r_unlock(c->hash);
			break;
		case SEC_IPSEC:
			if (!r_valid_contact(c)||!c->security||!c->security->data.ipsec ){
				LOG(L_DBG,"DBG:"M_NAME":P_security_200: Contact expired or no IPSec info\n");
				r_unlock(c->hash);
				goto error;
			}
			i = c->security->data.ipsec;
			
			/* P_Out_Rpl */
			sprintf(out_rpl,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
				pcscf_ipsec_P_Out_Rpl,
				c->host.len,c->host.s,
				i->port_uc,
				pcscf_ipsec_host,
				pcscf_ipsec_port_s,
				i->spi_uc,
				i->ealg.len,i->ealg.s,
				i->ck.len,i->ck.s,
				i->alg.len,i->alg.s,
				i->ik.len,i->ik.s	);					
	
			/* P_Out_Req */
			sprintf(out_req,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
				pcscf_ipsec_P_Out_Req,
				c->host.len,c->host.s,
				i->port_us,
				pcscf_ipsec_host,
				pcscf_ipsec_port_c,
				i->spi_us,
				i->ealg.len,i->ealg.s,
				i->ck.len,i->ck.s,
				i->alg.len,i->alg.s,
				i->ik.len,i->ik.s	);								
			/* P_Out_Inc_Rpl */
			sprintf(inc_rpl,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
				pcscf_ipsec_P_Inc_Rpl,
				c->host.len,c->host.s,
				i->port_us,
				pcscf_ipsec_host,
				pcscf_ipsec_port_c,
				i->spi_pc,
				i->ealg.len,i->ealg.s,
				i->ck.len,i->ck.s,
				i->alg.len,i->alg.s,
				i->ik.len,i->ik.s	);								
				
			if (expires<=0) {
				/* Deregister */
				c->reg_state = DEREGISTERED;
				r_act_time();
				c->expires = time_now + 60;
			}			
			r_unlock(c->hash);
		
			//print_r(L_CRIT);
			
			/* run the IPSec scripts */	
			/* Registration */
			execute_cmd(out_rpl);		
			execute_cmd(out_req);		
			execute_cmd(inc_rpl);
			break;
	}
	
	return CSCF_RETURN_TRUE;
ret_false:
	return CSCF_RETURN_FALSE;
error:
	return CSCF_RETURN_ERROR;
}
Esempio n. 4
0
/**
 * Process the 200 response for REGISTER and creates the first Security-Associations.
 * The rest of the SA are not set.
 * could come over that one. 
 * @param rpl - the 200 response
 * @param str1 - not used
 * @param str2 - not used
 * @returns 1 if ok, 0 if not
 */
int P_IPSec_200(struct sip_msg *rpl,char *str1, char *str2)
{
	struct sip_msg *req;
	struct hdr_field *hdr;	
	str sec_cli;
	struct hdr_field *h;
	struct via_body *vb;
	r_contact *c;
	r_ipsec *i;
	int expires;
	char out_rpl[256],out_req[256],inc_rpl[256];

	req = cscf_get_request_from_reply(rpl);
	if (!req){
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_200: No transactional request found.\n");
		goto error;
	}	
	/* just to jump out if no IPSec is employed - the info is already saved */
	sec_cli = cscf_get_security_client(req,&hdr);
	if (!sec_cli.len){
		LOG(L_DBG,"DBG:"M_NAME":P_ipsec_200: No Security-Client header found.\n");
		goto error; 
	}

	/* find the expires (reg or dereg?) */
	expires = cscf_get_max_expires(req);
	
	/* get the IPSec info from the registrar */
	
	vb = cscf_get_first_via(req,&h);
//	if (!h||!h->parsed){
//		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_200: Error extracting sender's id.\n");
//		goto error;
//	}		
//	vb = (struct via_body*) h->parsed;
	
	LOG(L_DBG,"DBG:"M_NAME":P_ipsec_200: Looking for <%d://%.*s:%d> \n",
		vb->proto,vb->host.len,vb->host.s,vb->port);

	c = get_r_contact(vb->host,vb->port,vb->proto);
		
	r_act_time();
	if (!c){
		LOG(L_ERR,"ERR:"M_NAME":P_ipsec_200: Contact not found\n");		
		goto error;
	}
	if (!r_valid_contact(c)||!c->ipsec){
		LOG(L_DBG,"DBG:"M_NAME":P_ipsec_200: Contact expired or no IPSec info\n");
		r_unlock(c->hash);
		goto error;
	}
	
	i = c->ipsec;
		
	/* P_Out_Rpl */
	sprintf(out_rpl,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
		pcscf_ipsec_P_Out_Rpl,
		c->host.len,c->host.s,
		i->port_uc,
		pcscf_ipsec_host,
		pcscf_ipsec_port_s,
		i->spi_uc,
		i->ealg.len,i->ealg.s,
		i->ck.len,i->ck.s,
		i->alg.len,i->alg.s,
		i->ik.len,i->ik.s	);					

	/* P_Out_Req */
	sprintf(out_req,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
		pcscf_ipsec_P_Out_Req,
		c->host.len,c->host.s,
		i->port_us,
		pcscf_ipsec_host,
		pcscf_ipsec_port_c,
		i->spi_us,
		i->ealg.len,i->ealg.s,
		i->ck.len,i->ck.s,
		i->alg.len,i->alg.s,
		i->ik.len,i->ik.s	);								
	/* P_Out_Inc_Rpl */
	sprintf(inc_rpl,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
		pcscf_ipsec_P_Inc_Rpl,
		c->host.len,c->host.s,
		i->port_us,
		pcscf_ipsec_host,
		pcscf_ipsec_port_c,
		i->spi_pc,
		i->ealg.len,i->ealg.s,
		i->ck.len,i->ck.s,
		i->alg.len,i->alg.s,
		i->ik.len,i->ik.s	);								
		
	if (expires<=0) {
		/* Deregister */
		c->reg_state = DEREGISTERED;
		r_act_time();
		c->expires = time_now + 60;
	}			
	r_unlock(c->hash);

	//print_r(L_CRIT);
	
	/* run the IPSec scripts */	
	/* Registration */
	execute_cmd(out_rpl);		
	execute_cmd(out_req);		
	execute_cmd(inc_rpl);
	return 1;	
error:
	return 0;	
}