/**
 * 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
/**
 * Processes a notification and updates the registrar info.
 * @param n - the notification
 * @param expires - the Subscription-Status expires parameter
 * @returns 1 on success, 0 on error
 */
int r_notification_process(r_notification *n,int expires)
{
	r_registration *r;
	r_regcontact *rc;	
	r_contact *c;
	struct sip_uri puri;
	enum Reg_States reg_state;
	int expires2;
	r_subscription *s=0;
	
	r_notification_print(n);	
	if (!n) return 0;
	
	r_act_time();
	r = n->registration;
	while(r){
		
		rc = r->contact;
		while(rc){
			if (parse_uri(rc->uri.s,rc->uri.len,&puri)<0){
				LOG(L_ERR,"ERR:"M_NAME":r_notification_process: Error parsing Contact URI <%.*s>\n",
					rc->uri.len,rc->uri.s);
				goto next;
			}
//			LOG(L_CRIT,"DBG:"M_NAME":r_notification_process: refreshing contacts <%.*s> [%d]\n",rc->uri.len,rc->uri.s,rc->expires);
			if (rc->state==IMS_REGINFO_TERMINATED){
				reg_state = DEREGISTERED;
				expires2 = time_now+30;
				c = update_r_contact(puri.host,puri.port_no,puri.proto,
					0,&reg_state,&expires2,0,0,0);
				if (c) {
					LOG(L_DBG,"DBG:"M_NAME":r_notification_process: expired contact <%.*s>\n",
						c->uri.len,c->uri.s);
					r_unlock(c->hash);					
				}
			}else{
				reg_state = REGISTERED;
				expires2 = rc->expires+time_now;
				c = update_r_contact(puri.host,puri.port_no,puri.proto,
					0,&reg_state,&expires2,0,0,0);
				if (c) {
					LOG(L_DBG,"DBG:"M_NAME":r_notification_process: refreshing contact <%.*s> [%d]\n",
						c->uri.len,c->uri.s,rc->expires);
					r_unlock(c->hash);					
				}

			}
next:				
			rc = rc->next;	
		}
		s = get_r_subscription(r->aor);
		if (s){
			update_r_subscription(s,expires);
			subs_unlock(s->hash);
		}
		r = r->next;
	}

	return 1;
}
示例#3
0
r_public* get_matching_wildcard_psi(str aor)
{
	r_public *p=0;
	t_regexp_unit *t;
	regex_t exp;
	char *c,*temp;
	int len;
	int errcode;
	
	p = registrar[r_hash_size].head;
	
	r_lock(r_hash_size);
	
	while (p)
	{
		
		for(t=p->regexp->head;t;t=t->next)
		{
			LOG(L_DBG,"get_matching_wildcard_psi match %.*s with %s\n",aor.len,aor.s,t->s);
			
			c=shm_malloc((aor.len)+1);
			memcpy(c,aor.s,aor.len);
			c[aor.len]='\0';
			
			
					errcode=regcomp(&(exp),t->s,REG_ICASE|REG_EXTENDED|REG_NOSUB);
					if(errcode!=0)
					{
						// there was an error
						LOG(L_DBG,"there was at least ONE error in regcomp %i\n",errcode);
						//shm_free(temp); temp=NULL;
						len=regerror(errcode,&(exp),NULL,0);
						temp=shm_malloc(len);
						regerror(errcode,&(exp),temp,len);
						LOG(L_DBG,"and that was %s",temp);
						shm_free(temp); temp=NULL;
						//shm_free(newwpsi);
						r_unlock(r_hash_size);
						return NULL;
					}
					
			
			if (regexec(&(exp),c,0,NULL,0)==0)
			{
				//LOG(L_DBG,"A match has been produced!!!!!\n");
				shm_free(c);
				return p;
			} else 
			{
				//LOG(L_ERR,"there was no match\n");
			}
			shm_free(c);				 
		}		
		p=p->next;
	}
	LOG(L_ERR,"get_r_public (Trying wildcard PSI) found no match\n");
	r_unlock(r_hash_size);
	
	return 0;
}
示例#4
0
/**
 * Expires all the contacts of public identities that are related to the given private id
 * @param private_id - private identity to expire contacts for
 */
void r_private_expire(str private_id)
{	
	int expire,i;
	r_public *p;
	r_contact *c;

	r_act_time();
	expire = time_now;
	
	for(i=0;i<r_hash_size;i++){
		r_lock(i);
			for(p = registrar[i].head;p;p=p->next){
				if (p->s){
					lock_get(p->s->lock);
						if (p->s->private_identity.len == private_id.len &&
							strncasecmp(p->s->private_identity.s,private_id.s,private_id.len)==0){
								for(c=p->head;c;c=c->next)
									c->expires = expire;								
							}
					lock_release(p->s->lock);
				}
			}
		r_unlock(i);
	}
	print_r(L_ALERT);
}
示例#5
0
文件: main.c 项目: camilo1729/distem
void* thread_fn(void* arg) {
	lli slee, start, end;
	lli loops_ps = loops_per_sec;
	double lratio = 1.0 - ratio;
	double wratio = lratio / (1. - lratio);
	lli loops, i;
	int syncl = sync_barrier;
	int local_finish;
	long long int interval = *((long long int*)arg);
	while(1)
	{
		r_lock();  /* begin reading */
		if (syncl) {
			pthread_barrier_wait(&barrier); // this can't fail according to docs
		}
		local_finish = finished;
		r_unlock();

		if (local_finish) {
			break;
		}

		start = GET_TIME();
		mysleep(interval);
		end = GET_TIME();
		slee = end - start;
		loops = (lli)(loops_ps * slee * wratio / 1000000.0);
		for (i=0; i < loops; i++) {
			LOOP();
		}
	}
	return 0;
}
示例#6
0
/**
 * Searches for a r_public record and returns it.
 * \note Aquires the lock on the hash slot on success, so release it when you are done.
 * @param aor - the address of record to look for
 * @returns - the r_public found, 0 if not found
 */
r_public* get_r_public(str aor)
{
	r_public *p=0;
	unsigned int hash;
	hash = get_aor_hash(aor,r_hash_size);
	r_lock(hash);
	p = registrar[hash].head;
	while(p){
		if (p->aor.len == aor.len &&
			strncasecmp(p->aor.s,aor.s,aor.len)==0) return p;
		p = p->next;
	}
	r_unlock(hash);
	
	/*
	 * Here i plan to put the function that tries to match the aor with the wPSI
	 * There might be an issue 
	 * if i return this locked, then i have to wait for the lock in the next one...
	 * mmmh... might be an issue
	 * */
	 if (scscf_support_wildcardPSI)
	 	return(get_matching_wildcard_psi(aor));
	 else
	 	return 0;
	 
}
示例#7
0
/**
 * Expires all the contacts for the given public id
 * @param public_id - public identity to expire contacts for
 */
void r_public_expire(str public_id)
{	
	int expire;
	r_public *r_pub;
	r_contact * r_cont ;
	
	r_act_time();
	expire = time_now;
	
	r_pub	=	get_r_public(public_id);
	
	if (!r_pub){
		LOG(L_ERR,"ERR:"M_NAME":set_expires: identity not found in registrar <%.*s>\n",public_id.len,public_id.s);
		return;
	}
	r_cont = r_pub->head;
	
	while(r_cont!=NULL){
		r_cont->expires = expire;
		r_cont=r_cont->next;
	}
	
	r_unlock(r_pub->hash);
	print_r(L_ALERT);
}
示例#8
0
/**
 * Debug print the contents of the entire registrar.
 * @param log_level - logging level
 */
void print_r(int log_level)
{
	r_public *p;
	r_contact *c;
	r_subscriber *s;
	int i;
	if (debug<log_level) return; /* to avoid useless calls when nothing will be printed */
	r_act_time();
	LOG(log_level,ANSI_GREEN"INF:"M_NAME":----------  Registrar Contents begin --------\n");
	for(i=0;i<r_hash_size;i++){
		r_lock(i);
			p = registrar[i].head;
			while(p){
				LOG(log_level,ANSI_GREEN"INF:"M_NAME":[%4d] P: <"ANSI_BLUE"%.*s"ANSI_GREEN"> R["ANSI_MAGENTA"%2d"ANSI_GREEN"] Early-IMS: <"ANSI_YELLOW"%.*s"ANSI_GREEN"> \n",i,
					p->aor.len,p->aor.s,p->reg_state,p->early_ims_ip.len,p->early_ims_ip.s);
				
				if (p->ccf1.len) LOG(log_level,ANSI_GREEN"INF:"M_NAME":         CCF1: <"ANSI_MAGENTA"%.*s"ANSI_GREEN"> CCF2: <"ANSI_MAGENTA"%.*s"ANSI_GREEN"> \n",
					p->ccf1.len,p->ccf1.s,p->ccf2.len,p->ccf2.s);
				if (p->ecf1.len) LOG(log_level,ANSI_GREEN"INF:"M_NAME":         ECF1: <"ANSI_MAGENTA"%.*s"ANSI_GREEN"> ECF2: <"ANSI_MAGENTA"%.*s"ANSI_GREEN"> \n",
					p->ecf1.len,p->ecf1.s,p->ecf2.len,p->ecf2.s);
					
				c = p->head;
				while(c){
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":         C: <"ANSI_RED"%.*s"ANSI_GREEN"> Exp:["ANSI_MAGENTA"%4ld"ANSI_GREEN"]\n",
						c->uri.len,c->uri.s,c->expires-time_now);					
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":         UP: {"ANSI_BLUE" iptv[%s], text[%s], data[%s], audio[%s], video[%s], control[%s], isfocus[%s], automata[%s], application[%s]\n          mobility[%s]"ANSI_GREEN" }\n", 
						((c->user_pref->iptv == TRUE)?"yes":"no"),
						((c->user_pref->text == TRUE)?"yes":"no"),
						((c->user_pref->data == TRUE)?"yes":"no"),
						((c->user_pref->audio == TRUE)?"yes":"no"),
						((c->user_pref->video == TRUE)?"yes":"no"),
						((c->user_pref->control == TRUE)?"yes":"no"),
						((c->user_pref->isfocus == TRUE)?"yes":"no"),
						((c->user_pref->automata == TRUE)?"yes":"no"),
						((c->user_pref->application== TRUE)?"yes":"no"),
						((c->user_pref->mobility.val_list[0] == MOBILE)?"mobile":"fixed")  
						) ;
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":           Path:"ANSI_YELLOW"%.*s"ANSI_GREEN"\n",c->path.len,c->path.s);
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":           UA: <%.*s>\n",
						c->ua.len,c->ua.s);
					c = c->next;
				}
				s = p->shead;
				while(s){
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":         S: Event["ANSI_BLUE"%d"ANSI_GREEN
						"] Exp:["ANSI_MAGENTA"%4ld"ANSI_GREEN"] <"ANSI_CYAN"%.*s"ANSI_GREEN"> \n",
						s->event,s->expires-time_now,s->subscriber.len,s->subscriber.s);					
					s = s->next;
				}
				p = p->next;
			} 		
		r_unlock(i);
	}
	LOG(log_level,"INF:"M_NAME":----------  Registrar Contents end ----------\n");
}
示例#9
0
r_public* get_r_public_wpsi(str pi)
{
	r_public *p=0;
	r_lock(r_hash_size);
	p = registrar[r_hash_size].head;
	while(p){
		if (p->aor.len == pi.len &&
			strncasecmp(p->aor.s,pi.s,pi.len)==0) return p;
		p = p->next;
	}
	r_unlock(r_hash_size);
	return 0;
	
}
示例#10
0
/**
 * Searches for a r_public record and returns its expiration value.
 * @param aor - the address of record to look for
 * @returns - the expiration of the r_public if found or -999 if not found
 */
int get_r_public_expires(str aor)
{
	int max_expires=-999;
	r_contact *c;
	r_public *p=get_r_public(aor);
	if (!p) return -999;
	r_act_time();
	for(c=p->head;c;c=c->next)
		if (c->expires-time_now>max_expires){
			max_expires = c->expires - time_now;
		}
	r_unlock(p->hash);
	return max_expires;
}
示例#11
0
/**
 * Searches for a r_public record and returns it.
 * \note Aquires the lock on the hash slot on success, so release it when you are done.
 * @param aor - the address of record to look for
 * @returns - the r_public found, 0 if not found
 */
r_public* get_r_public(str aor)
{
	r_public *p=0;
	unsigned int hash;
	hash = get_aor_hash(aor,r_hash_size);
	r_lock(hash);
	p = registrar[hash].head;
	while(p){
		if (p->aor.len == aor.len &&
			strncasecmp(p->aor.s,aor.s,aor.len)==0) return p;
		p = p->next;
	}
	r_unlock(hash);
	return 0;
}
示例#12
0
/**
 * Destroy the registrar
 */
void r_storage_destroy()
{
	int i;
	r_contact *c,*nc;
	for(i=0;i<r_hash_size;i++){
		r_lock(i);
			c = registrar[i].head;
			while(c){
				nc = c->next;
				free_r_contact(c);
				c = nc;
			}
		r_unlock(i);
		lock_dealloc(registrar[i].lock);
	}
	shm_free(registrar);	
}
示例#13
0
/**
 * Destroy the registrar
 */
void r_storage_destroy()
{
	int i;
	r_public *p,*np;
	for(i=0;i<r_hash_size;i++){
		r_lock(i);
			p = registrar[i].head;
			while(p){
				np = p->next;
				free_r_public(p);
				p = np;
			}
		r_unlock(i);
		lock_dealloc(registrar[i].lock);
	}
	shm_free(registrar);
}
示例#14
0
/**
 * Searches for a r_contact contact and returns it.
 * \note Will lock the hash_slot if found! So release it when you are done!
 * @param host - the IP in string format
 * @param port - the port number
 * @param transport - the transport type
 * @param sos_mask - type of registration
 * @returns - the r_contact found, 0 if not found
 */
r_contact* get_r_contact(str host,int port,int transport, r_reg_type sos_mask)
{
	r_contact *c=0;
	unsigned int hash;
	if (!registrar) return 0;
	hash = get_contact_hash(host,port,transport,r_hash_size);
	r_lock(hash);
	c = registrar[hash].head;
	while(c){
		if (c->port == port &&
			(c->sos_flag & sos_mask) && 
//			c->transport == transport && /* because xten doesn't care about protocols */ 
			c->host.len == host.len &&
			strncasecmp(c->host.s,host.s,host.len)==0) return c;
		c = c->next;
	}
	r_unlock(hash);
	return 0;
}
示例#15
0
/**
 * Debug print the contents of the entire registrar.
 * @param log_level - logging level
 */
void print_r(int log_level)
{
	r_public *p;
	r_contact *c;
	r_subscriber *s;
	int i;
	if (debug<log_level) return; /* to avoid useless calls when nothing will be printed */
	r_act_time();
	LOG(log_level,ANSI_GREEN"INF:"M_NAME":----------  Registrar Contents begin --------\n");
	for(i=0;i<r_hash_size;i++){
		r_lock(i);
			p = registrar[i].head;
			while(p){
				LOG(log_level,ANSI_GREEN"INF:"M_NAME":[%4d] P: <"ANSI_BLUE"%.*s"ANSI_GREEN"> R["ANSI_MAGENTA"%2d"ANSI_GREEN"] Early-IMS: <"ANSI_YELLOW"%.*s"ANSI_GREEN"> \n",i,
					p->aor.len,p->aor.s,p->reg_state,p->early_ims_ip.len,p->early_ims_ip.s);
				
				if (p->ccf1.len) LOG(log_level,ANSI_GREEN"INF:"M_NAME":         CCF1: <"ANSI_MAGENTA"%.*s"ANSI_GREEN"> CCF2: <"ANSI_MAGENTA"%.*s"ANSI_GREEN"> \n",
					p->ccf1.len,p->ccf1.s,p->ccf2.len,p->ccf2.s);
				if (p->ecf1.len) LOG(log_level,ANSI_GREEN"INF:"M_NAME":         ECF1: <"ANSI_MAGENTA"%.*s"ANSI_GREEN"> ECF2: <"ANSI_MAGENTA"%.*s"ANSI_GREEN"> \n",
					p->ecf1.len,p->ecf1.s,p->ecf2.len,p->ecf2.s);
					
				c = p->head;
				while(c){
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":         C: <"ANSI_RED"%.*s"ANSI_GREEN"> Exp:["ANSI_MAGENTA"%4ld"ANSI_GREEN"]\n",
						c->uri.len,c->uri.s,c->expires-time_now);					
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":           Path:"ANSI_YELLOW"%.*s"ANSI_GREEN"\n",c->path.len,c->path.s);
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":           UA: <%.*s>\n",
						c->ua.len,c->ua.s);
					c = c->next;
				}
				s = p->shead;
				while(s){
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":         S: Event["ANSI_BLUE"%d"ANSI_GREEN
						"] Exp:["ANSI_MAGENTA"%4ld"ANSI_GREEN"] <"ANSI_CYAN"%.*s"ANSI_GREEN"> \n",
						s->event,s->expires-time_now,s->subscriber.len,s->subscriber.s);					
					s = s->next;
				}
				p = p->next;
			} 		
		r_unlock(i);
	}
	LOG(log_level,"INF:"M_NAME":----------  Registrar Contents end ----------\n");
}
示例#16
0
r_contact * get_next_em_r_contact(str pub_id, contact_t * crt_contact){

	r_contact * c = NULL;
	r_public * crt_pub_id;
	
	unsigned int hash;
	if (!registrar) return 0;
	for(hash=0; hash<r_hash_size;hash++){
		r_lock(hash);

		for(c = registrar[hash].head;c!=NULL; c=c->next){
			if(!(c->sos_flag & EMERG_REG))
				continue;

			if(crt_contact->uri.len == c->uri.len && 
				strncasecmp(crt_contact->uri.s, c->uri.s, crt_contact->uri.len) ==0){

				LOG(L_DBG,"DBG:"M_NAME":update_contacts: found contact %.*s, but on the same host\n",
					   crt_contact->uri.len, crt_contact->uri.s);
				continue;
			}


			crt_pub_id = c->head;
			if(!crt_pub_id)
				continue;

			if(crt_pub_id->aor.len == pub_id.len &&
					strncasecmp(crt_pub_id->aor.s,pub_id.s,pub_id.len)==0) {
				
				
				LOG(L_DBG,"DBG:"M_NAME":get_next_em_r_contact: found contact %.*s:%i\n",
					   c->host.len, c->host.s, c->port);
				
				return c;
			}
		}
		r_unlock(hash);
	}
	return 0;
}
示例#17
0
/**
 * Process a Push Profile Request and return the Answer for it.
 * @param ppr - the PPR Diameter request
 * @returns the PPA Diameter answer
 */
AAAMessage* Cx_PPA(AAAMessage * ppr)
{
	AAAMessage	*ppa_msg;
	str ppr_data;
	ims_subscription *imss;
	int i,j;
	r_public *pu;
	str ccf1,ccf2,ecf1,ecf2;

	ppa_msg	= cdpb.AAACreateResponse(ppr);
	if (!ppa_msg) return 0;	
	
	if((ppr_data=Cx_get_user_data(ppr)).len != 0){
		LOG(L_INFO,"INFO:"M_NAME":Cx_PPA(): Received a User_Data PPR!\n");
		imss=parse_user_data(ppr_data);
		print_user_data(L_ALERT,imss);
		
		for(i=0;i<imss->service_profiles_cnt;i++)
			for(j=0;j<imss->service_profiles[i].public_identities_cnt;j++){				
				pu = update_r_public(imss->service_profiles[i].public_identities[j].public_identity,
					0,&imss,0,0,0,0);
				if (!pu) continue;
				r_unlock(pu->hash);
			}			
	}
	else{
		if (Cx_get_charging_info(ppr,&ccf1,&ccf2,&ecf1,&ecf2)){
			LOG(L_INFO,"INFO:"M_NAME":Cx_PPA(): Received a Charging Info PPR - NOT IMPLEMENTED\n");
			//TODO find all r_public that should be updated and update
		}
	}	
	Cx_add_vendor_specific_appid(ppa_msg,IMS_vendor_id_3GPP,IMS_Cx,0 /*IMS_Cx*/);
	Cx_add_auth_session_state(ppa_msg,1);		
	
	Cx_add_result_code(ppa_msg,DIAMETER_SUCCESS);
	#ifdef WITH_IMS_PM
		ims_pm_diameter_answer(ppa_msg);
	#endif			
	return ppa_msg;
}
示例#18
0
/**
 * Loads the registrar data from the last snapshot.
 * @returns 1 on success or 0 on failure
 */
int load_snapshot_registrar()
{
	bin_data x;
	r_contact *c;
	int k,max;
	FILE *f;
	
	switch (pcscf_persistency_mode){
		case NO_PERSISTENCY:
			k=0;

		case WITH_FILES:
			f = bin_load_from_file_open(pcscf_persistency_location,"pregistrar");		
			if (!f) return 0;
			bin_alloc(&x,128*1024);
			k=bin_load_from_file_read(f,&x);
			max = x.max;
			x.max=0;
			LOG(L_INFO,"INFO:"M_NAME":load_snapshot_registrar: max %d len %d\n",x.max,x.len);
			while(x.max<x.len){
				c = bin_decode_r_contact(&x);
				if (!c) return 0;
				LOG(L_INFO,"INFO:"M_NAME":load_snapshot_registrar: Loaded r_contact for <%.*s>\n",c->uri.len,c->uri.s);
				r_lock(c->hash);
				c->prev = registrar[c->hash].tail;
				c->next = 0;
				if (registrar[c->hash].tail) registrar[c->hash].tail->next = c;
				registrar[c->hash].tail = c;
				if (!registrar[c->hash].head) registrar[c->hash].head = c;
				r_unlock(c->hash);
				
				memmove(x.s,x.s+x.max,x.len-x.max);
				x.len -= x.max;
				x.max = max;
				k=bin_load_from_file_read(f,&x);
				max = x.max;
				x.max = 0;				
			}
			bin_free(&x);
			bin_load_from_file_close(f);
			k = 1;
			break;
			
		case WITH_DATABASE_BULK:
			k=bin_load_from_db(&x, P_REGISTRAR);
			x.max=0;
			LOG(L_INFO,"INFO:"M_NAME":load_snapshot_registrar: max %d len %d\n",x.max,x.len);
			while(x.max<x.len){
				c = bin_decode_r_contact(&x);
				if (!c) return 0;
				LOG(L_INFO,"INFO:"M_NAME":load_snapshot_registrar: Loaded r_contact for <%.*s>\n",c->uri.len,c->uri.s);
				r_lock(c->hash);
				c->prev = registrar[c->hash].tail;
				c->next = 0;
				if (registrar[c->hash].tail) registrar[c->hash].tail->next = c;
				registrar[c->hash].tail = c;
				if (!registrar[c->hash].head) registrar[c->hash].head = c;
				r_unlock(c->hash);
			}
			bin_free(&x);
			break;
			
		case WITH_DATABASE_CACHE:
			k=bin_load_from_db(NULL, P_REGISTRAR); //ignore x, x is empty
			break;
			
		default:
			LOG(L_ERR,"ERR:"M_NAME":load_snapshot_registrar: Can't resume because no such mode %d\n",pcscf_persistency_mode);
			k=0;
	}	
	if (!k) goto error;
	
	
	return 1;
error:
	return 0;
	
}
示例#19
0
/**
 * Updates the r_public with the new reg_state and ims_subscription values.
 * 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 aor - the address of record
 * @param reg_state - new registration state, NULL if no update necessary
 * @param s - the new subscription attached, NULL if no update necessary
 * @returns the update r_public or NULL on error
 */
r_public* update_r_public(str aor,enum Reg_States *reg_state,ims_subscription **s,
	str *ccf1, str *ccf2, str *ecf1, str *ecf2)
{
	r_public *p=0;
	//LOG(L_CRIT,"update_r_public():with aor %.*s\n",aor.len,aor.s);
	
	if ((*s)->wpsi) {
		p = get_r_public_wpsi(aor);
	} else {
		p = get_r_public(aor);
	}
	
	if (!p){
		//LOG(L_DBG,"updating a new r_public profile\n");			 
		if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s){
			p = add_r_public(aor,*reg_state,*s);
			
			if (!p) return p;			
			if (ccf1) {
				if (p->ccf1.s) shm_free(p->ccf1.s);
				STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1");
			}
			if (ccf2) {
				if (p->ccf2.s) shm_free(p->ccf2.s);
				STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2");
			}
			if (ecf1) {
				if (p->ecf1.s) shm_free(p->ecf1.s);
				STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1");
			}
			if (ecf2) {
				if (p->ecf2.s) shm_free(p->ecf2.s);
				STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2");
			}
			//LOG(L_DBG,"update_r_public():  it was actually adding\n");
			return p;
		}
		else return 0;
	}else{
		//LOG(L_DBG,"updating a not so new r_public profile\n");		
		if (reg_state) p->reg_state = *reg_state;
		if (*s) {
			
			if (p->s){
				lock_get(p->s->lock);
				if (p->s->ref_count==1){
					free_user_data(p->s);
				}else{
					p->s->ref_count--;
					lock_release(p->s->lock);
				}
			}			
			p->s = *s;
			lock_get(p->s->lock);
				p->s->ref_count++;
			lock_release(p->s->lock);
			
			
			 if ((*s)->wpsi)
			 {	
			 	
			 	 p->s=NULL; 
			 	 			 	 
			 	 if (p->prev) p->prev->next=p->next;
			 	 else registrar[r_hash_size].head=p->next;	
			 	 if (p->next) p->next->prev=p->prev;
			 	 else registrar[r_hash_size].tail=p->prev;
			 	 
			 	 free_r_public(p);
			 	 r_unlock(r_hash_size);			 
			 	 p=add_r_public(aor,0,*s);
			 	 
			 }
			
			
		}
		if (ccf1) {
			if (p->ccf1.s) shm_free(p->ccf1.s);
			STR_SHM_DUP( &(p->ccf1), ccf1,"SHM CCF1");
		}
		if (ccf2) {
			if (p->ccf2.s) shm_free(p->ccf2.s);
			STR_SHM_DUP( &(p->ccf2), ccf2,"SHM CCF2");
		}
		if (ecf1) {
			if (p->ecf1.s) shm_free(p->ecf1.s);
			STR_SHM_DUP( &(p->ecf1), ecf1,"SHM ECF1");
		}
		if (ecf2) {
			if (p->ecf2.s) shm_free(p->ecf2.s);
			STR_SHM_DUP( &(p->ecf2), ecf2,"SHM ECF2");
		}
		//LOG(L_DBG,"update_r_public():    return normaly\n");
		return p;
	}
out_of_memory:
	return p;	
}
示例#20
0
/**
 * Creates the full reginfo XML.
 * @param pv - the r_public to create for
 * @param event_type - event type
 * @param subsExpires - subscription expiration
 * @returns the str with the XML content
 */
str r_get_reginfo_full(void *pv,int event_type,long *subsExpires)
{		
	str x={0,0};
	str buf,pad;	
	char bufc[MAX_REGINFO_SIZE],padc[MAX_REGINFO_SIZE];

	r_public *p=(r_public*)pv,*p2;
	r_contact *c;
	r_contact_param *cp;
	ims_public_identity *pi;
	int i,j;
	unsigned int hash;
	
	buf.s = bufc;
	buf.len=0;
	pad.s = padc;
	pad.len=0;
	
	*subsExpires = r_update_subscription_status(p);
	
	STR_APPEND(buf,xml_start);
	sprintf(pad.s,r_reginfo_s.s,"%d",r_full.len,r_full.s);
	pad.len = strlen(pad.s);
	STR_APPEND(buf,pad);
	
	
	if (p->s){
		for(i=0;i<p->s->service_profiles_cnt;i++)
			for(j=0;j<p->s->service_profiles[i].public_identities_cnt;j++){
				pi = &(p->s->service_profiles[i].public_identities[j]);
				if (!pi->barring){
					hash = get_aor_hash(pi->public_identity,r_hash_size);
					if (hash == p->hash) /* because we already have the lock on p->hash */
						p2 = get_r_public_nolock(pi->public_identity);
					else 
						p2 = get_r_public(pi->public_identity);
					if (p2){
						if (p2->reg_state==REGISTERED)
							sprintf(pad.s,registration_s.s,p2->aor.len,p2->aor.s,p2,r_active.len,r_active.s);
						else 
							sprintf(pad.s,registration_s.s,p2->aor.len,p2->aor.s,p2,r_terminated.len,r_terminated.s);
						pad.len = strlen(pad.s);
						STR_APPEND(buf,pad);
						c = p2->head;
						while(c){
							if(c->qvalue != -1) {
								float q = (float)c->qvalue/1000;
								sprintf(pad.s,contact_s_q.s,c,r_active.len,r_active.s,r_registered.len,r_registered.s,c->expires-time_now, q);
							}
							else
								sprintf(pad.s,contact_s.s,c,r_active.len,r_active.s,r_registered.len,r_registered.s,c->expires-time_now);
							pad.len = strlen(pad.s);
							STR_APPEND(buf,pad);							
							STR_APPEND(buf,uri_s);
							STR_APPEND(buf,c->uri);
							STR_APPEND(buf,uri_e);
							for(cp=c->parameters;cp;cp=cp->next){
								sprintf(pad.s,unknown_param_s.s,cp->name.len,cp->name.s);
								pad.len = strlen(pad.s);
								STR_APPEND(buf,pad);
								STR_APPEND(buf,cp->value);
								STR_APPEND(buf,unknown_param_e);
							}
							STR_APPEND(buf,contact_e);
							c = c->next;
						}
						STR_APPEND(buf,registration_e);
						if (p2->hash != p->hash) r_unlock(p2->hash);
					}
				}
			}				
	}

	STR_APPEND(buf,r_reginfo_e);

	
	x.s = pkg_malloc(buf.len+1);
	if (x.s){
		x.len = buf.len;
		memcpy(x.s,buf.s,buf.len);
		x.s[x.len]=0;
	}
	return x;
}
示例#21
0
/**
 * Save this subscription.
 * @param msg - the SIP SUBSCRIBE message
 * @param str1 - not used
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if allowed, #CSCF_RETURN_FALSE if not, #CSCF_RETURN_ERROR on error
 */
int S_subscribe(struct sip_msg *msg,char *str1,char *str2)
{
	int ret=CSCF_RETURN_FALSE;
	struct sip_uri puri;
	str uri={0,0};
	str event;
	int event_i=IMS_EVENT_NONE;
	int expires=0,expires_time=0;
	str subscriber;
	r_public *p=0;
	r_subscriber *s=0,*new_s=0;
	dlg_t *dialog=0;

	LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Saving SUBSCRIBE\n");

	/* First check the parameters */
	if (msg->first_line.type!=SIP_REQUEST)
	{
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a request\n");
		goto error;
	}		
	if (msg->first_line.u.request.method.len != 9 ||
		memcmp(msg->first_line.u.request.method.s,"SUBSCRIBE",9)!=0)
	{
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: This message is not a SUBSCRIBE\n");
		goto error;
	}

	/* 1. Get the event 	*/
	event = cscf_get_event(msg);
	if (event.len!=3||strncasecmp(event.s,"reg",3)!=0){
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Accepting only <Event: reg>. Found: <%.*s>\n",
			event.len,event.s);
		ret = CSCF_RETURN_FALSE;	
		goto done;
	} 
	if (event.len==0 && strncasecmp(event.s,"reg",3)==0)
		event_i = IMS_EVENT_REG;
	
	/* 2. Get the target of the SUBSCRIBE from RequestURI */
	if (msg->new_uri.s) uri = msg->new_uri;
	else uri = msg->first_line.u.request.uri;
	
	if (parse_uri(uri.s, uri.len, &puri) < 0) {
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error parsing uri <%.*s>\n",
			uri.len,uri.s);
		goto error;
	}
	uri.len = lookup_sip.len+puri.user.len+1+puri.host.len;
	uri.s = pkg_malloc(uri.len);
	if (!uri.s){
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Error allocating %d bytes\n",uri.len);
		goto error;
	}
	uri.len=0;
	memcpy(uri.s,lookup_sip.s,lookup_sip.len);
	uri.len+=lookup_sip.len;
	memcpy(uri.s+uri.len,puri.user.s,puri.user.len);
	uri.len+=puri.user.len;
	uri.s[uri.len++]='@';
	memcpy(uri.s+uri.len,puri.host.s,puri.host.len);
	uri.len+=puri.host.len;

	/* 3. Get the Subscriber's Identity */
	subscriber = cscf_get_contact(msg);
	if (!subscriber.len){
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Contact empty.\n");
		ret =  CSCF_RETURN_FALSE;
		goto done;		
	}
	LOG(L_DBG,"DBG:"M_NAME":S_subscribe: Contact <%.*s>.\n",
		subscriber.len,subscriber.s);
	
	p = get_r_public(uri);

	/* Registration is possible even if the user is not registered... so just create one */
	if (!p){
		p = add_r_public(uri,0,0);
	}
	if (!p){		
		LOG(L_ERR,"ERR:"M_NAME":S_subscribe: Identity not found and error on creation <%.*s>\n",
			uri.len,uri.s);
		ret =  CSCF_RETURN_FALSE;
		goto done;
	}
		
	expires = cscf_get_expires_hdr(msg,0);
	if (expires == -1) expires = subscription_default_expires;
	if (expires > 0) {
		if (expires < subscription_min_expires) expires = subscription_min_expires;
		if (expires > subscription_max_expires) expires = subscription_max_expires;
		r_act_time();
		expires_time = expires + time_now;
		
		/* get the old subscriber - if any */
		s = get_r_subscriber(p,subscriber,event_i);	
		if (!s){
			/* create a new dialog */
			if (tmb.new_dlg_uas(msg, 200, &dialog) < 0) {		
				LOG(L_ERR,"ERR:"M_NAME":S_subscribe:  Error while creating dialog state\n");
				ret = CSCF_RETURN_FALSE;
				goto error;
			}
		}else
			dialog = s->dialog;
		
		/* update the subscriber */
		if ((new_s=update_r_subscriber(p,subscriber,event_i,&expires_time,dialog))!=0){		
			//if (!s)	/* Only on first subscription, not on refreshes, send a notify */
				S_event_reg(p,0,new_s,IMS_REGISTRAR_SUBSCRIBE,0);
			ret = CSCF_RETURN_TRUE;
		}
		else
			ret = CSCF_RETURN_FALSE;	
	}else{
		/* Unsubscribe */
		/* get the old subscriber - if any */
		r_act_time();
		s = get_r_subscriber(p,subscriber,event_i);	
		if (s) {
			s->expires = time_now;
			S_event_reg(p,0,s,IMS_REGISTRAR_UNSUBSCRIBE,1);
			del_r_subscriber(p,s);
		}
		ret = CSCF_RETURN_TRUE;
	}
done:	
	r_unlock(p->hash);
	if (expires ==0 )S_SUBSCRIBE_reply(msg,200,MSG_REG_UNSUBSCRIBE_OK,&expires,&uri);
	else S_SUBSCRIBE_reply(msg,200,MSG_REG_SUBSCRIBE_OK,&expires,&uri);
	if (uri.s) pkg_free(uri.s);
	return ret;
error:
	if (p) r_unlock(p->hash);
	if (uri.s) pkg_free(uri.s);
	ret=CSCF_RETURN_FALSE;
	return ret;	
}
示例#22
0
/**
 * Check if this message quallifies for a subscription.
 * Only 3 entities can subscribe:
 * - the user agent to its own state
 * - the P-CSCF specified in a Path header for that user
 * - AS (not implemented yet
 * \todo Allow also the AS listed in iFC and not belonging to a 3rd party 
 * @param msg - the SIP SUBSCRIBE message
 * @param str1 - not used
 * @param str2 - not used
 * @returns #CSCF_RETURN_TRUE if allowed, #CSCF_RETURN_FALSE if not, #CSCF_RETURN_ERROR on error
 */
int S_can_subscribe(struct sip_msg *msg,char *str1,char *str2)
{
	int ret=CSCF_RETURN_FALSE;
	struct sip_uri puri;
	str uri={0,0};
	str event;
	str asserted_id;
	r_public *p=0;
	r_contact *c=0;
	ims_public_identity *pi=0;
	int i,j;

	LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Checking if allowed to SUBSCRIBE\n");

	/* First check the parameters */
	if (msg->first_line.type!=SIP_REQUEST)
	{
		LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: This message is not a request\n");
		goto error;
	}		
	if (msg->first_line.u.request.method.len != 9 ||
		memcmp(msg->first_line.u.request.method.s,"SUBSCRIBE",9)!=0)
	{
		LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: This message is not a SUBSCRIBE\n");
		goto error;
	}

	/* 1. Get the event 	*/
	event = cscf_get_event(msg);
	if (event.len!=3||strncasecmp(event.s,"reg",3)!=0){
		LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Accepting only <Event: reg>. Found: <%.*s>\n",
			event.len,event.s);
		ret = CSCF_RETURN_FALSE;	
		goto done;
	} 
	
	/* 2. Get the target of the SUBSCRIBE from RequestURI */
	if (msg->new_uri.s) uri = msg->new_uri;
	else uri = msg->first_line.u.request.uri;
	
	if (parse_uri(uri.s, uri.len, &puri) < 0) {
		LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Error parsing uri <%.*s>\n",
			uri.len,uri.s);
		goto error;
	}
	uri.len = lookup_sip.len+puri.user.len+1+puri.host.len;
	uri.s = pkg_malloc(uri.len);
	if (!uri.s){
		LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Error allocating %d bytes\n",uri.len);
		goto error;
	}
	uri.len=0;
	memcpy(uri.s,lookup_sip.s,lookup_sip.len);
	uri.len+=lookup_sip.len;
	memcpy(uri.s+uri.len,puri.user.s,puri.user.len);
	uri.len+=puri.user.len;
	uri.s[uri.len++]='@';
	memcpy(uri.s+uri.len,puri.host.s,puri.host.len);
	uri.len+=puri.host.len;

	/* 3. Check if the asserted identity is in the same group with the ReqURI */
	asserted_id = cscf_get_asserted_identity(msg);
	if (!asserted_id.len){
		LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: P-Asserted-Identity empty.\n");
		ret =  CSCF_RETURN_FALSE;
		goto done;		
	}
	LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: P-Asserted-Identity <%.*s>.\n",
		asserted_id.len,asserted_id.s);
	
	p = get_r_public(uri);
	
	if (!p){
		LOG(L_ERR,"ERR:"M_NAME":S_can_subscribe: Identity not found <%.*s>\n",
			uri.len,uri.s);
		ret =  CSCF_RETURN_FALSE;
		goto done;
	}
	if (p->aor.len == asserted_id.len &&
		strncasecmp(p->aor.s,asserted_id.s,asserted_id.len)==0)
	{
		LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Identity found as AOR <%.*s>\n",
			uri.len,uri.s);
		ret = CSCF_RETURN_TRUE;
		goto done;
	}
	if (p->s){
		for(i=0;i<p->s->service_profiles_cnt;i++)
			for(j=0;j<p->s->service_profiles[i].public_identities_cnt;j++)
			{
				pi = &(p->s->service_profiles[i].public_identities[j]);
				if (!pi->barring &&
					pi->public_identity.len == asserted_id.len &&
					strncasecmp(pi->public_identity.s,asserted_id.s,asserted_id.len)==0)
				{
					LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Identity found in SP[%d][%d]\n",
						i,j);
					ret = CSCF_RETURN_TRUE;
					goto done;
				}	
			}
	}
	
	/* 4. Check if it present in any of the Path headers */
	c=p->head;

	while(c){
		if (c->path.len){
			for(i=0;i<c->path.len-asserted_id.len;i++)
				if (strncasecmp(c->path.s+i,asserted_id.s,asserted_id.len)==0){
					LOG(L_DBG,"DBG:"M_NAME":S_can_subscribe: Identity found in Path <%.*s>\n",
						c->path.len,c->path.s);
					ret = CSCF_RETURN_TRUE;
					goto done;
				}
		}
		c = c->next;
	}
	
	
done:
	if (p) r_unlock(p->hash);
	if (uri.s) pkg_free(uri.s);
	return ret;
error:
	if (p) r_unlock(p->hash);
	if (uri.s) pkg_free(uri.s);
	ret=CSCF_RETURN_ERROR;
	return ret;	
}
示例#23
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;
}
示例#24
0
文件: security.c 项目: asyn/openvims
/**
 * Process the 401 response for REGISTER and creates the first Security-Associations.
 * IPSEc: Only the SA for P_Inc_Req - Incoming Requests is set now as the next REGISTER
 * could come over that one. 
 * @param rpl - the 401 response
 * @param str1 - not used
 * @param str2 - not used
 * @returns 1 if ok, 0 if not
 */
int P_security_401(struct sip_msg *rpl,char *str1, char *str2)
{
	struct sip_msg *req;
	struct hdr_field *hdr;	
	str sec_hdr,sec_srv={0,0};
	r_security_type sec_type;
	char cmd[256];
	r_contact *c;
	r_ipsec *ipsec;
	float sec_q=-1;
	str auth;

	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_401: No transactional request found.\n");
		goto error;
	}
	auth = cscf_get_authenticate(rpl,&hdr);
	if (!auth.len){
		LOG(L_ERR,"ERR:"M_NAME":P_security_401: No WWW-Authenticate header found.\n");
		goto ret_false; 
	}
	
	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_401: No Security-Client header found.\n");
		goto ret_false;
	}
	LOG(L_INFO,"DBG:"M_NAME":P_security_401: Security-Client header found : <%.*s>.\n", sec_hdr.len, sec_hdr.s);	


	/* save data into registrar */
	c = save_contact_security(req, auth, sec_hdr, sec_type, sec_q);	
	if (!c) goto error;
	switch(sec_type){
		case SEC_NONE:
			break;
		case SEC_TLS:			
			/* try to add the Security-Server header */		
			sec_srv.len = s_security_server_s.len+sec_hdr.len+s_security_server_e.len;
			sec_srv.s = pkg_malloc(sec_srv.len);
			if (!sec_srv.s){
				LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error allocating %d pkg bytes \n",sec_srv.len);
				goto error;
			}
			sec_srv.len=0;
			STR_APPEND(sec_srv,s_security_server_s);
			STR_APPEND(sec_srv,sec_hdr);
			STR_APPEND(sec_srv,s_security_server_e);

			if (!cscf_add_header(rpl,&sec_srv,HDR_OTHER_T)) {
				LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error adding header <%.*s> \n",sec_srv.len,sec_srv.s);
				pkg_free(sec_srv.s);
				goto error;
			}
			break;
		case SEC_IPSEC:
			ipsec = c->security_temp->data.ipsec;
			/* try to add the Security-Server header */
			sprintf(cmd,"Security-Server: ipsec-3gpp; ealg=%.*s; alg=%.*s; spi-c=%d; spi-s=%d; port-c=%d; port-s=%d; q=0.1\r\n",
				ipsec->r_ealg.len,ipsec->r_ealg.s,
				ipsec->r_alg.len,ipsec->r_alg.s,
				ipsec->spi_pc,ipsec->spi_ps,
				pcscf_ipsec_port_c,pcscf_ipsec_port_s);
			
			sec_srv.len = strlen(cmd);
			sec_srv.s = pkg_malloc(sec_srv.len);
			if (!sec_srv.s){
				LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error allocating %d pkg bytes \n",sec_srv.len);
				goto error;
			}
			memcpy(sec_srv.s,cmd,sec_srv.len);
			if (!cscf_add_header(rpl,&sec_srv,HDR_OTHER_T)) {
				LOG(L_ERR,"ERR:"M_NAME":P_security_401: Error adding header <%.*s> \n",sec_srv.len,sec_srv.s);
				pkg_free(sec_srv.s);
				goto error;
			}
	
			/* run the IPSec script */	
			/* P_Inc_Req */
			sprintf(cmd,"%s %.*s %d %s %d %d %.*s %.*s %.*s %.*s",
				pcscf_ipsec_P_Inc_Req,
				c->host.len,c->host.s,
				ipsec->port_uc,
				pcscf_ipsec_host,
				pcscf_ipsec_port_s,
				ipsec->spi_ps,
				ipsec->ealg.len,ipsec->ealg.s,
				ipsec->ck.len,ipsec->ck.s,
				ipsec->alg.len,ipsec->alg.s,
				ipsec->ik.len,ipsec->ik.s);

			r_unlock(c->hash);
				
			execute_cmd(cmd);
			break;						
	}
	
	return CSCF_RETURN_TRUE;
ret_false:
	return CSCF_RETURN_FALSE;
error:
	return CSCF_RETURN_ERROR;
}
示例#25
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;
}
示例#26
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;	
}
示例#27
0
/**
 * Debug print the contents of the entire registrar.
 */
void print_r(int log_level)
{
	r_public *p;
	r_contact *c;
	int i,j;
#ifdef SER_MOD_INTERFACE
	if (!is_printable(log_level))
#else		
	if (debug<log_level)
#endif	
		return; /* to avoid useless calls when nothing will be printed */	r_act_time();
	LOG(log_level,"INF:"M_NAME":----------  Registrar Contents begin --------\n");
	if (!registrar) return;
	for(i=0;i<r_hash_size;i++){
		r_lock(i);
		c = registrar[i].head;
		while(c){
			LOG(log_level,ANSI_GREEN"INF:"M_NAME":[%4d] C: <"ANSI_RED"%d://%.*s:%d"ANSI_GREEN"> Exp:["ANSI_MAGENTA"%4ld"ANSI_GREEN"] R:["ANSI_MAGENTA"%2d"ANSI_GREEN"] SOS:["ANSI_MAGENTA"%c"ANSI_GREEN"] <%.*s>\n",i,
			c->transport,c->host.len,c->host.s,c->port,
				c->expires-time_now,c->reg_state,
				(c->sos_flag & EMERG_REG)?'X':' ',
				c->uri.len,c->uri.s);					
			for(j=0;j<c->service_route_cnt;j++)
				LOG(log_level,ANSI_GREEN"INF:"M_NAME":         SR: <"ANSI_YELLOW"%.*s"ANSI_GREEN">\n",c->service_route[j].len,c->service_route[j].s);
			if(c->pinhole) {
				if (c->pinhole->nat_addr.len>=4)
					LOG(log_level,ANSI_GREEN"INF:"M_NAME":        NAT:<"ANSI_CYAN"%d://%d.%d.%d.%d:%d"ANSI_GREEN">\n",
						c->pinhole->proto,
						c->pinhole->nat_addr.u.addr[0],
						c->pinhole->nat_addr.u.addr[1],
						c->pinhole->nat_addr.u.addr[2],
						c->pinhole->nat_addr.u.addr[3],
						(unsigned short)c->pinhole->nat_port);
				
			} 
			if (c->security){
				switch(c->security->type){
					case SEC_NONE:
						break;						
					case SEC_TLS:
						if (c->security->data.tls)
						LOG(log_level,ANSI_GREEN"INF:"M_NAME":        TLS: %.*s tls://%.*s:%d\n",
							c->security->sec_header.len,c->security->sec_header.s,
							c->host.len,c->host.s,c->security->data.tls->port_tls);
						break;
					case SEC_IPSEC:
						if (c->security->data.ipsec)
						LOG(log_level,ANSI_GREEN"INF:"M_NAME":        IPSec: UAS: %d:%d->%d  UAC: %d:%d<-%d E[%.*s] I[%.*s]\n",
							c->security->data.ipsec->spi_uc,c->security->data.ipsec->port_uc,c->security->data.ipsec->spi_ps,
							c->security->data.ipsec->spi_us,c->security->data.ipsec->port_us,c->security->data.ipsec->spi_pc,
							c->security->data.ipsec->ealg.len,c->security->data.ipsec->ealg.s,c->security->data.ipsec->alg.len,c->security->data.ipsec->alg.s);
				}					
			}
			if (c->security_temp){
				switch(c->security_temp->type){
					case SEC_NONE:
						break;						
					case SEC_TLS:
						if (c->security_temp->data.tls)
						LOG(log_level,ANSI_GREEN"INF:"M_NAME":        TLS: %.*s tls://%.*s:%d\n",
							c->security_temp->sec_header.len,c->security_temp->sec_header.s,
							c->host.len,c->host.s,c->security_temp->data.tls->port_tls);						
						break;
					case SEC_IPSEC:
						if (c->security_temp->data.ipsec)
						LOG(log_level,ANSI_GREEN"INF:"M_NAME":        Temp.IPSec: UAS: %d:%d->%d  UAC: %d:%d<-%d E[%.*s] I[%.*s]\n",
							c->security_temp->data.ipsec->spi_uc,c->security_temp->data.ipsec->port_uc,c->security_temp->data.ipsec->spi_ps,
							c->security_temp->data.ipsec->spi_us,c->security_temp->data.ipsec->port_us,c->security_temp->data.ipsec->spi_pc,
							c->security_temp->data.ipsec->ealg.len,c->security_temp->data.ipsec->ealg.s,c->security_temp->data.ipsec->alg.len,c->security_temp->data.ipsec->alg.s);
				}					
			}
			
			p = c->head;
			while(p){
				LOG(log_level,ANSI_GREEN"INF:"M_NAME":          P: D[%c] <"ANSI_BLUE"%.*s"ANSI_GREEN"> \n",
					(p->is_default?'X':' '),p->aor.len,p->aor.s);
				p = p->next;
			}
			c = c->next;
		}
		r_unlock(i);
	}
	LOG(log_level,"INF:"M_NAME":----------  Registrar Contents end ----------\n");
}
示例#28
0
/**
 * Creates a snapshots of the registrar and then calls the dumping function.
 * @returns 1 on success or 0 on failure
 */
int make_snapshot_registrar()
{
	bin_data x={0,0,0};
	r_contact *c;
	int i,k;	
	time_t unique = time(0);
	FILE *f;
	
	
	switch (pcscf_persistency_mode) {
		case NO_PERSISTENCY:
			return 0;
			
		case WITH_FILES:
			f = bin_dump_to_file_create(pcscf_persistency_location,"pregistrar",unique);
			if (!f) return 0;
			
			for(i=0;i<r_hash_size;i++){
				if (!bin_alloc(&x,1024)) goto error;		
				r_lock(i);
				c = registrar[i].head;
				if (c){
					while(c){
						if (!bin_encode_r_contact(&x,c)) goto error;
						c = c->next;
					}
					r_unlock(i);
					k = bind_dump_to_file_append(f,&x);
					if (k!=x.len) {
						LOG(L_ERR,"ERR:"M_NAME":make_snapshot_registrar: error while dumping to file - only wrote %d bytes of %d \n",k,x.len);
						r_unlock(i);
						bin_free(&x);
						return 0;
					} 
				}
				else r_unlock(i);
				bin_free(&x);
			}
			return bind_dump_to_file_close(f,pcscf_persistency_location,"pregistrar",unique);

			break;
			
		case WITH_DATABASE_BULK:
			if (!bin_alloc(&x,1024)) goto error;		
			for(i=0;i<r_hash_size;i++){
				r_lock(i);
				c = registrar[i].head;
				while(c){
					if (!bin_encode_r_contact(&x,c)) goto error;
					c = c->next;
				}
				r_unlock(i);
			}
			return bin_dump_to_db(&x, P_REGISTRAR);

		case WITH_DATABASE_CACHE:
			return bin_dump_to_db(NULL, P_REGISTRAR); //ignore x, x is empty
		default:
			LOG(L_ERR,"ERR:"M_NAME":make_snapshot_registrar: Snapshot done but no such mode %d\n",pcscf_persistency_mode);
			return 0;
		
	}

error:
	if (x.s) bin_free(&x);	
	return 0;
}