コード例 #1
0
/**
 * Updates the r_contact with the new security values.
 * @param host - the host part of the contact, in string
 * @param port - the port number of the contact
 * @param transport - the transport of the contact
 * @param uri - URI of the contact
 * @param reg_state - Registration state
 * @param expires - expires in
 * @param ipsec - the new IPSec tunnel
 * @returns the newly added r_public, 0 on error
 */
r_contact* update_r_contact_sec(str host,int port,int transport,
	str *uri,enum Reg_States *reg_state,int *expires,
	r_security *s, int * sos_reg)
{
	r_contact *c = NULL;
	r_reg_type sos_mask =  NORMAL_REG;
	
	if(sos_reg && (*sos_reg)>0){
			LOG(L_DBG,"DBG:"M_NAME":update_r_contact_sec: with sos uri param\n");
			sos_mask = EMERG_REG;
	}
	
	c = get_r_contact(host,port,transport, sos_mask);
	if (!c){
		if (uri&&reg_state){
			c = add_r_contact(host,port,transport,*uri,*reg_state,*expires,(str*) 0,0,0,sos_mask);
			c->security_temp = s;
			r_unlock(c->hash);
			return c;
		}
		else return 0;
	}else{
		if (c->security_temp){
			P_security_drop(c,c->security_temp);
			free_r_security(c->security_temp);
		}		
		c->security_temp = s;
		c->sos_flag = sos_mask;
		r_unlock(c->hash);
		return c;
	}
}
コード例 #2
0
/** 
 * Gets the contact structure with the uri the same as the one given.
 * \note Aquires the lock on the hash_slot on success, so release it when you are done.
 * @param host - the host part of the contact, in string
 * @param port - the port number of the contact
 * @param transport - the transport of the contact 
 * @return the r_nat_dest on success or NULL on failure
 */
r_nat_dest* get_r_nat_pinhole(str host, int port, int transport) {
	r_contact * contact;
	
	contact = get_r_contact(host, port, transport, ANY_REG);
	if(contact != NULL) {
		return contact -> pinhole;
	}
	LOG(L_ERR, "ERR"M_NAME":get_r_nat_pinhole: cannot find contact %d://%.*s:%d\n", transport,host.len, host.s, port);
	return NULL;
}
コード例 #3
0
ファイル: registrar_storage.c プロジェクト: asyn/openvims
/**
 * Updates the r_contact with the new expires, ua valu, path value.
 * \note If not found it is added
 * \note Must be called with a lock on the hash slot to avoid races
 * @param p - the r_public to add to
 * @param uri - the contact uri
 * @param expires - new expires value, NULL if not necessary
 * @param ua - new user agent string, NULL if no update necessary
 * @param path - Path header received at registration
 * @returns the updated r_contact or NULL on error
 */
r_contact* update_r_contact(r_public *p,str uri,int *expires, str *ua,str *path)
{
	r_contact *c;
	
	if (!p) return 0;
	c = get_r_contact(p,uri);
	if (!c){
		if (expires && ua && path)
			return add_r_contact(p,uri,*expires,*ua,*path);
		else return 0;
	}else{
		if (expires) c->expires = *expires;
		if (ua){
			if (c->ua.s) shm_free(c->ua.s);
			c->ua.s = shm_malloc(ua->len);
			if (!c->ua.s) {
				LOG(L_ERR,"ERR:"M_NAME":update_r_contact(): Error allocating %d bytes\n",
					ua->len);
				c->ua.len=0;
				return 0;
			}
			c->ua.len = ua->len;
			memcpy(c->ua.s,ua->s,ua->len);
		}
		if (path){
			if (c->path.s) shm_free(c->path.s);
			c->path.s = shm_malloc(path->len);
			if (!c->path.s) {
				LOG(L_ERR,"ERR:"M_NAME":update_r_contact(): Error allocating %d bytes\n",
					path->len);
				c->path.len=0;
				return 0;
			}
			c->path.len = path->len;
			memcpy(c->path.s,path->s,path->len);
		}
		return c;
	}
}
コード例 #4
0
ファイル: security.c プロジェクト: asyn/openvims
/**
 * 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;
}
コード例 #5
0
ファイル: security.c プロジェクト: asyn/openvims
/**
 * 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;
}
コード例 #6
0
ファイル: security.c プロジェクト: asyn/openvims
/**
 * 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;	
}
コード例 #7
0
/**
 * Updates the r_contact with the new states
 * If not found, it will be inserted
 * \note Aquires the lock on the hash_slot on success, so release it when you are done.
 * @param host - the host part of the contact, in string
 * @param port - the port number of the contact
 * @param transport - the transport of the contact
 * @param uri - URI of the contact
 * @param reg_state - Registration state
 * @param expires - expires in
 * @param service_route - array of service routes
 * @param service_route_cnt - the size of the array above
 * @param pinhole - NAT pin hole
 * @param sos_flag - flag for Emergency Registration
 * @returns the updated added r_contact, 0 on error
 */
r_contact* update_r_contact(str host,int port,int transport,
	str *uri,enum Reg_States *reg_state,int *expires,str **service_route,
	int *service_route_cnt, r_nat_dest **pinhole, int *sos_flag)
{
	r_contact *c=0;
	int i;
	r_reg_type sos_mask;

	if(sos_flag && (*sos_flag>0))
		sos_mask = EMERG_REG;
	else	sos_mask = NORMAL_REG;

	c = get_r_contact(host,port,transport, sos_mask);
	if (!c){
		if (uri&&reg_state && expires && service_route && service_route_cnt)
			return pinhole?add_r_contact(host,port,transport,*uri,*reg_state,*expires,*service_route,*service_route_cnt, *pinhole, sos_mask):
					   add_r_contact(host,port,transport,*uri,*reg_state,*expires,*service_route,*service_route_cnt, 0,  sos_mask);
		else return 0;
	}else{
		/* first drop the old temporary public ids */
		if (c->reg_state==DEREGISTERED && reg_state && *reg_state==REGISTERED){
			while(c->head){
				del_r_public(c,c->head);
			}
		}

		if (uri) {
			if (c->uri.s) shm_free(c->uri.s);
			STR_SHM_DUP(c->uri,*uri,"update_r_contact");
		}
		if (reg_state) c->reg_state = *reg_state;
		if (expires) c->expires = *expires;
		if (service_route){
			if (c->service_route){
				for(i=0;i<c->service_route_cnt;i++)
					if (c->service_route[i].s) shm_free(c->service_route[i].s);
				shm_free(c->service_route);
				c->service_route=0;
				c->service_route_cnt=0;
			}
			if (*service_route&&*service_route_cnt){
				c->service_route = shm_malloc((*service_route_cnt)*sizeof(str));
				if (!c->service_route){
					LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n",
						(*service_route_cnt)*sizeof(str));					
					goto out_of_memory;					
				}else{
					for(i=0;i<*service_route_cnt;i++)
						STR_SHM_DUP(c->service_route[i],(*service_route)[i],"new_r_contact");
					c->service_route_cnt = *service_route_cnt;											
				}			
			}
		}
		if (pinhole) c->pinhole = *pinhole;
		c->sos_flag = sos_mask;
		return c;
	}
	
out_of_memory:
	return c;	
}