Example #1
0
int run_timer_check(void *e_data, void *data, void *r_data)
{
	unsigned int i=hash_index;
	reg_record_t *rec = (reg_record_t*)e_data;
	struct timer_check_data *t_check_data = (struct timer_check_data*)data;
	time_t now = t_check_data->now;
	str *s_now = t_check_data->s_now;

	switch(rec->state){
	case REGISTERING_STATE:
	case AUTHENTICATING_STATE:
		break;
	case WRONG_CREDENTIALS_STATE:
	case REGISTER_TIMEOUT_STATE:
	case INTERNAL_ERROR_STATE:
	case REGISTRAR_ERROR_STATE:
		reg_print_record(rec);
		new_call_id_ftag_4_record(rec, s_now);
		if(send_register(i, rec, NULL)==1) {
			rec->last_register_sent = now;
			rec->state = REGISTERING_STATE;
		} else {
			rec->registration_timeout = now + rec->expires - timer_interval;
			rec->state = INTERNAL_ERROR_STATE;
		}
		break;
	case REGISTERED_STATE:
		/* check if we need to re-register */
		if (now < rec->registration_timeout) {
			break;
		}
	case NOT_REGISTERED_STATE:
		if(send_register(i, rec, NULL)==1) {
			rec->last_register_sent = now;
			rec->state = REGISTERING_STATE;
		} else {
			rec->registration_timeout = now + rec->expires - timer_interval;
			rec->state = INTERNAL_ERROR_STATE;
		}
		break;
	default:
		LM_ERR("Unexpected state [%d] for rec [%p]\n", rec->state, rec);
	}

	return 0; /* continue list traversal */
}
Example #2
0
int add_record(uac_reg_map_t *uac, str *now)
{
	reg_record_t *rec, *prev_rec, *record;
	unsigned int size, expires;
	dlg_t *td;
	str call_id_ftag;
	char *p;

	if (uac->expires.s && uac->expires.len) {
		if (str2int(&uac->expires, &expires)<0) {
			LM_ERR("unable to get expiry from [%.*s]\n",
				uac->expires.len, uac->expires.s);
			return -1;
		}
	} else {
		expires = default_expires;
	}

	/* Reserve space for record */
	size = sizeof(reg_record_t) + MD5_LEN +
		uac->to_uri.len + uac->from_uri.len + uac->registrar_uri.len +
		uac->auth_user.len + uac->auth_password.len +
		uac->contact_uri.len + uac->contact_params.len + uac->proxy_uri.len;
	record = (reg_record_t *)shm_malloc(size);
	if(!record) {
		LM_ERR("oom\n");
		return -1;
	}
	memset(record, 0, size);

	record->expires = expires;

	td = &(record->td);
	p = (char *)(record + 1);

	/* Setting the td->id */
	gen_call_id_ftag(&uac->to_uri, now, &call_id_ftag);
	memcpy(p, call_id_ftag.s, call_id_ftag.len);
	td->id.call_id.s = p;
	td->id.call_id.len = MD5_LEN - 5;
	td->id.loc_tag.s = p + MD5_LEN - 5;
	td->id.loc_tag.len = 5;
	p += MD5_LEN;

	//td->id.rem_tag.s = NULL;
	//td->id.rem_tag.len = 0;

	/* Setting the CSeq */
	td->loc_seq.value = 0;
	td->loc_seq.is_set = 1;
	//td->loc_seq.rem_tag.s = NULL;
	//td->loc_seq.rem_tag.len = 0;

	/* Setting the remote URI */
	td->rem_uri.s = p;
	td->rem_uri.len = uac->to_uri.len;
	memcpy(p, uac->to_uri.s, uac->to_uri.len);
	p += uac->to_uri.len;

	/* Setting the outbound proxy */
	if (uac->proxy_uri.s && uac->proxy_uri.len) {
		td->obp.s = p;
		td->obp.len = uac->proxy_uri.len;
		memcpy(p, uac->proxy_uri.s, uac->proxy_uri.len);
		p += uac->proxy_uri.len;
	}

	/* Setting the local URI */
	if(uac->from_uri.s && uac->from_uri.len) {
		LM_DBG("got from [%.*s]\n", uac->from_uri.len, uac->from_uri.s);
		td->loc_uri.s = p;
		td->loc_uri.len = uac->from_uri.len;
		memcpy(p, uac->from_uri.s, uac->from_uri.len);
		p += uac->from_uri.len;
	} else {
		td->loc_uri.s = td->rem_uri.s;
		td->loc_uri.len = td->rem_uri.len;
	}

	/* Setting the Remote target URI */
	td->rem_target.s = p;
	td->rem_target.len = uac->registrar_uri.len;
	memcpy(p, uac->registrar_uri.s, uac->registrar_uri.len);
	p += uac->registrar_uri.len;

	/* Setting the Local/Remote Display Name */
	//td->loc_dname.s = td->rem_dname.s = NULL;
	//td->loc_dname.len = td->rem_dname.len = 0;

	//td->T_flags = 0;
	td->state = DLG_CONFIRMED;

	/* Setting the Route set */
	//td->route_set = NULL;
	/* Setting the hooks */
	//td->hooks <- no hooks for REGISTER
	/* Setting the socket */
	td->send_sock = uac->send_sock;
	/* Done with td */

	if (uac->auth_user.s && uac->auth_user.len) {
		record->auth_user.s = p;
		record->auth_user.len = uac->auth_user.len;
		memcpy(p, uac->auth_user.s, uac->auth_user.len);
		p += uac->auth_user.len;
	}

	if (uac->auth_password.s && uac->auth_password.len) {
		record->auth_password.s = p;
		record->auth_password.len = uac->auth_password.len;
		memcpy(p, uac->auth_password.s, uac->auth_password.len);
		p += uac->auth_password.len;
	}

	record->contact_uri.s = p;
	record->contact_uri.len = uac->contact_uri.len;
	memcpy(p, uac->contact_uri.s, uac->contact_uri.len);
	p += uac->contact_uri.len;

	if (uac->contact_params.s && uac->contact_params.len) {
		record->contact_params.s = p;
		record->contact_params.len = uac->contact_params.len;
		memcpy(p, uac->contact_params.s, uac->contact_params.len);
		p += uac->contact_params.len;
	}

	reg_print_record(record);

	rec = reg_htable[uac->hash_code].first;
	if (rec) {
		while(rec) {
			prev_rec = rec;
			rec = rec->next;
		}
		prev_rec->next = record;
		record->prev = prev_rec;
	} else {
		reg_htable[uac->hash_code].first = record;
		record->prev = record->next = NULL;
	}
	
	return 0;
}
Example #3
0
void timer_check(unsigned int ticks, void* param)
{
	unsigned int i=hash_index;
	reg_record_t *rec;
	char *p;
	int len;
	time_t now;
	str str_now = {NULL, 0};

	now = time(0);

	p = int2str((unsigned long)(time(0)), &len);
	if (p && len>0) {
		str_now.s = (char *)pkg_malloc(len);
		if (str_now.s) {
			memcpy(str_now.s, p, len);
			str_now.len = len;
		} else {
			LM_ERR("oom\n");
			return;
		}
	}

	lock_get(&reg_htable[i].lock);
	//LM_DBG("checking ... [%d] on htable[%d]\n", (unsigned int)now, i);
	rec = reg_htable[i].first;
	while (rec) {
		switch(rec->state){
		case REGISTERING_STATE:
		case AUTHENTICATING_STATE:
		case WRONG_CREDENTIALS_STATE:
			break;
		case REGISTER_TIMEOUT_STATE:
		case INTERNAL_ERROR_STATE:
		case REGISTRAR_ERROR_STATE:
			reg_print_record(rec);
			new_call_id_ftag_4_record(rec, &str_now);
			if(send_register(i, rec, NULL)==1) {
				rec->last_register_sent = now;
				rec->state = REGISTERING_STATE;
			} else {
				rec->registration_timeout = now + rec->expires - timer_interval;
				rec->state = INTERNAL_ERROR_STATE;
			}
			break;
		case REGISTERED_STATE:
			/* check if we need to re-register */
			if (now < rec->registration_timeout) {
				break;
			}
		case NOT_REGISTERED_STATE:
			if(send_register(i, rec, NULL)==1) {
				rec->last_register_sent = now;
				rec->state = REGISTERING_STATE;
			} else {
				rec->registration_timeout = now + rec->expires - timer_interval;
				rec->state = INTERNAL_ERROR_STATE;
			}
			break;
		default:
			LM_ERR("Unexpected state [%d] for rec [%p]\n", rec->state, rec);
		}
		rec = rec->next;
	}
	lock_release(&reg_htable[i].lock);

	if (str_now.s) {pkg_free(str_now.s);}

	hash_index = (++i)%reg_hsize;

	return;
}
Example #4
0
void reg_tm_cback(struct cell *t, int type, struct tmcb_params *ps)
{
	struct sip_msg *msg;
	reg_tm_cb_t *cb_param;
	int statuscode = 0;
	unsigned int exp = 0;
	reg_record_t *rec;
	struct hdr_field *c_ptr, *head_contact;
	struct uac_credential crd;
	contact_t *contact;
	struct authenticate_body *auth = NULL;
	static struct authenticate_nc_cnonce auth_nc_cnonce;
	HASHHEX response;
	str *new_hdr;
	time_t now;

	if(ps==NULL || ps->rpl==NULL) {
		LM_ERR("wrong ps parameter\n");
		return;
	}
	if(ps->param==NULL || *ps->param==NULL) {
		LM_ERR("null callback parameter\n");
		return;
	}
	cb_param = (reg_tm_cb_t *)*ps->param;
	if(cb_param->uac == NULL) {
		LM_ERR("null record\n");
		return;
	}
	statuscode = ps->code;
	now = time(0);
	LM_DBG("tm [%p] notification cb for %s [%d] reply at [%d]\n",
			t, (ps->rpl==FAKED_REPLY)?"FAKED_REPLY":"", statuscode, (unsigned int)now);

	if(statuscode<200) return;

	lock_get(&reg_htable[cb_param->hash_index].lock);
	rec = reg_htable[cb_param->hash_index].first;
	while(rec) {
		if (rec==cb_param->uac) {
			break;
		}
		rec = rec->next;
	}
	if(!rec) {
		LM_ERR("record [%p] not found on hash index [%d]\n",
		cb_param->uac, cb_param->hash_index);
		lock_release(&reg_htable[cb_param->hash_index].lock);
		return;
	}
	reg_print_record(rec);

	switch(statuscode) {
	case 200:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}
		if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
			LM_ERR("failed to parse headers\n");
			goto done;
		}
		if (msg->contact) {
			c_ptr = msg->contact;
			while(c_ptr) {
				if (c_ptr->type == HDR_CONTACT_T) {
					if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) {
						LM_ERR("failed to parse Contact body\n");
						goto done;
					}
				}
				c_ptr = c_ptr->next;
			}
		} else {
			LM_ERR("No contact header in received 200ok\n");
			goto done;
		}
		head_contact = msg->contact;
		contact = ((contact_body_t*)msg->contact->parsed)->contacts;
		while (contact) {
			/* Check for binding */
			if (contact->uri.len==rec->contact_uri.len &&
				strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){
				if (contact->expires && contact->expires->body.len) {
					if (str2int(&contact->expires->body, &exp)<0) {
						LM_ERR("Unable to extract expires from [%.*s]"
							" for binding [%.*s]\n",
							contact->expires->body.len,
							contact->expires->body.s,
							contact->uri.len, contact->uri.s);
					} else {
						rec->expires = exp;
					}
				}
				break;
			}
					
			/* get the next contact */
			if (contact->next == NULL) {
				contact = NULL;
				c_ptr = head_contact->next;
				while(c_ptr) {
					if (c_ptr->type == HDR_CONTACT_T) {
						head_contact = c_ptr;
						contact = ((contact_body_t*)c_ptr->parsed)->contacts;
						break;
					}
					c_ptr = c_ptr->next;
				}
			} else {
				contact = contact->next;
			}
		}
		rec->state = REGISTERED_STATE;
		rec->registration_timeout = now + rec->expires - timer_interval;
		break;

	case WWW_AUTH_CODE:
	case PROXY_AUTH_CODE:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}

		if (rec->auth_user.s==NULL || rec->auth_user.len==0 ||
			rec->auth_password.s==NULL || rec->auth_password.len==0) {
			LM_ERR("Credentials not provisioned\n");
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			lock_release(&reg_htable[cb_param->hash_index].lock);
			return;
		}

		if (statuscode==WWW_AUTH_CODE) {
			if (0 == parse_www_authenticate_header(msg))
				auth = get_www_authenticate(msg);
		} else if (statuscode==PROXY_AUTH_CODE) {
			if (0 == parse_proxy_authenticate_header(msg))
				auth = get_proxy_authenticate(msg);
		}
		if (auth == NULL) {
			LM_ERR("Unable to extract authentication info\n");
			goto done;
		}
		LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]"
			" opaque=[%.*s] qop=[%.*s]\n",
			auth->flags,
			auth->realm.len, auth->realm.s,
			auth->domain.len, auth->domain.s,
			auth->nonce.len, auth->nonce.s,
			auth->opaque.len, auth->opaque.s,
			auth->qop.len, auth->qop.s);

		switch(rec->state) {
		case REGISTERING_STATE:
			break;
		case AUTHENTICATING_STATE:
			/* We already sent an authenticated REGISTER and we are still challanged! */
			LM_ERR("Wrong credentials for \n");
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			lock_release(&reg_htable[cb_param->hash_index].lock);
			return;
		default:
			LM_ERR("Unexpected [%d] notification cb in state [%d]\n",
				statuscode, rec->state);
			goto done;
		}

		/* perform authentication */
		if (auth->realm.s && auth->realm.len) {
			crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len;
		} else {
			LM_ERR("No realm found\n");
			goto done;
		}
		crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len;
		crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len;

		memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce));
		uac_auth_api._do_uac_auth(&register_method, &rec->td.rem_target, &crd,
					auth, &auth_nc_cnonce, response);
		new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target,
					&crd, auth, &auth_nc_cnonce, response);
		if (!new_hdr) {
			LM_ERR("failed to build authorization hdr\n");
			goto done;
		}
		if(send_register(cb_param->hash_index, rec, new_hdr)==1) {
			rec->state = AUTHENTICATING_STATE;
		} else {
			rec->state = INTERNAL_ERROR_STATE;
		}
		break;

	default:
		if(statuscode<400 && statuscode>=300) {
			LM_ERR("Redirection not implemented yet\n");
			rec->state = INTERNAL_ERROR_STATE;
		} else {
			/* we got an error from the server */
			rec->state = REGISTRAR_ERROR_STATE;
			rec->registration_timeout = now + rec->expires - timer_interval;
			
		}
	}

	lock_release(&reg_htable[cb_param->hash_index].lock);

	return;
done:
	rec->state = INTERNAL_ERROR_STATE;
	rec->registration_timeout = now + rec->expires;
	lock_release(&reg_htable[cb_param->hash_index].lock);
	return;
}
Example #5
0
int run_reg_tm_cback(void *e_data, void *data, void *r_data)
{
	struct sip_msg *msg;
	int statuscode = 0;
	unsigned int exp = 0;
	reg_record_t *rec = (reg_record_t*)e_data;
	struct hdr_field *c_ptr, *head_contact;
	struct uac_credential crd;
	contact_t *contact;
	struct authenticate_body *auth = NULL;
	static struct authenticate_nc_cnonce auth_nc_cnonce;
	HASHHEX response;
	str *new_hdr;
	struct reg_tm_cback_data *tm_cback_data = (struct reg_tm_cback_data*)data;
	struct cell *t;
	struct tmcb_params *ps;
	time_t now;
	reg_tm_cb_t *cb_param;

	cb_param = tm_cback_data->cb_param;
	if (rec!=cb_param->uac) {
		/* no action on current list elemnt */
		return 0; /* continue list traversal */
	}

	t = tm_cback_data->t;
	ps = tm_cback_data->ps;
	now = tm_cback_data->now;

	reg_print_record(rec);

	if (ps->rpl==FAKED_REPLY)
		memset(&rec->td.forced_to_su, 0, sizeof(union sockaddr_union));
	else if (rec->td.forced_to_su.s.sa_family == AF_UNSPEC)
		rec->td.forced_to_su = t->uac[0].request.dst.to;

	statuscode = ps->code;
	switch(statuscode) {
	case 200:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}
		if (parse_headers(msg, HDR_EOH_F, 0) == -1) {
			LM_ERR("failed to parse headers\n");
			goto done;
		}
		if (msg->contact) {
			c_ptr = msg->contact;
			while(c_ptr) {
				if (c_ptr->type == HDR_CONTACT_T) {
					if (!c_ptr->parsed && (parse_contact(c_ptr)<0)) {
						LM_ERR("failed to parse Contact body\n");
						goto done;
					}
				}
				c_ptr = c_ptr->next;
			}
		} else {
			LM_ERR("No contact header in received 200ok\n");
			goto done;
		}
		head_contact = msg->contact;
		contact = ((contact_body_t*)msg->contact->parsed)->contacts;
		while (contact) {
			/* Check for binding */
			if (contact->uri.len==rec->contact_uri.len &&
				strncmp(contact->uri.s,rec->contact_uri.s,contact->uri.len)==0){
				if (contact->expires && contact->expires->body.len) {
					if (str2int(&contact->expires->body, &exp)<0) {
						LM_ERR("Unable to extract expires from [%.*s]"
							" for binding [%.*s]\n",
							contact->expires->body.len,
							contact->expires->body.s,
							contact->uri.len, contact->uri.s);
					}
				}
				break;
			}
					
			/* get the next contact */
			if (contact->next == NULL) {
				contact = NULL;
				c_ptr = head_contact->next;
				while(c_ptr) {
					if (c_ptr->type == HDR_CONTACT_T) {
						head_contact = c_ptr;
						contact = ((contact_body_t*)c_ptr->parsed)->contacts;
						break;
					}
					c_ptr = c_ptr->next;
				}
			} else {
				contact = contact->next;
			}
		}
		rec->state = REGISTERED_STATE;
		if (exp) rec->expires = exp;
		rec->registration_timeout = now + rec->expires - timer_interval;
		break;

	case WWW_AUTH_CODE:
	case PROXY_AUTH_CODE:
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}

		if (rec->auth_user.s==NULL || rec->auth_user.len==0 ||
			rec->auth_password.s==NULL || rec->auth_password.len==0) {
			LM_ERR("Credentials not provisioned\n");
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			/* action successfuly completed on current list element */
			return 1; /* exit list traversal */
		}

		if (statuscode==WWW_AUTH_CODE) {
			if (0 == parse_www_authenticate_header(msg))
				auth = get_www_authenticate(msg);
		} else if (statuscode==PROXY_AUTH_CODE) {
			if (0 == parse_proxy_authenticate_header(msg))
				auth = get_proxy_authenticate(msg);
		}
		if (auth == NULL) {
			LM_ERR("Unable to extract authentication info\n");
			goto done;
		}
		LM_DBG("flags=[%d] realm=[%.*s] domain=[%.*s] nonce=[%.*s]"
			" opaque=[%.*s] qop=[%.*s]\n",
			auth->flags,
			auth->realm.len, auth->realm.s,
			auth->domain.len, auth->domain.s,
			auth->nonce.len, auth->nonce.s,
			auth->opaque.len, auth->opaque.s,
			auth->qop.len, auth->qop.s);

		switch(rec->state) {
		case REGISTERING_STATE:
			break;
		case AUTHENTICATING_STATE:
			/* We already sent an authenticated REGISTER and we are still challanged! */
			LM_WARN("Wrong credentials for [%.*s]\n",
				rec->td.rem_uri.len, rec->td.rem_uri.s);
			rec->state = WRONG_CREDENTIALS_STATE;
			rec->registration_timeout = 0;
			/* action successfuly completed on current list element */
			return 1; /* exit list traversal */
		default:
			LM_ERR("Unexpected [%d] notification cb in state [%d]\n",
				statuscode, rec->state);
			goto done;
		}

		/* perform authentication */
		if (auth->realm.s && auth->realm.len) {
			crd.realm.s = auth->realm.s; crd.realm.len = auth->realm.len;
		} else {
			LM_ERR("No realm found\n");
			goto done;
		}
		crd.user.s = rec->auth_user.s; crd.user.len = rec->auth_user.len;
		crd.passwd.s = rec->auth_password.s; crd.passwd.len = rec->auth_password.len;

		memset(&auth_nc_cnonce, 0, sizeof(struct authenticate_nc_cnonce));
		uac_auth_api._do_uac_auth(&register_method, &rec->td.rem_target, &crd,
					auth, &auth_nc_cnonce, response);
		new_hdr = uac_auth_api._build_authorization_hdr(statuscode, &rec->td.rem_target,
					&crd, auth, &auth_nc_cnonce, response);
		if (!new_hdr) {
			LM_ERR("failed to build authorization hdr\n");
			goto done;
		}
		if(send_register(cb_param->hash_index, rec, new_hdr)==1) {
			rec->state = AUTHENTICATING_STATE;
		} else {
			rec->state = INTERNAL_ERROR_STATE;
		}
		pkg_free(new_hdr->s);
		new_hdr->s = NULL; new_hdr->len = 0;
		break;

	case 423: /* Interval Too Brief */
		msg = ps->rpl;
		if(msg==FAKED_REPLY) {
			LM_ERR("FAKED_REPLY\n");
			goto done;
		}
		if (0 == parse_min_expires(msg)) {
			rec->expires = (unsigned int)(long)msg->min_expires->parsed;
			if(send_register(cb_param->hash_index, rec, NULL)==1)
				rec->state = REGISTERING_STATE;
			else
				rec->state = INTERNAL_ERROR_STATE;
		} else {
			rec->state = REGISTRAR_ERROR_STATE;
			rec->registration_timeout = now + rec->expires - timer_interval;
		}
		break;

	case 408: /* Interval Too Brief */
		rec->state = REGISTER_TIMEOUT_STATE;
		rec->registration_timeout = now + rec->expires - timer_interval;
		break;

	default:
		if(statuscode<400 && statuscode>=300) {
			LM_ERR("Redirection not implemented yet\n");
			rec->state = INTERNAL_ERROR_STATE;
		} else {
			/* we got an error from the server */
			rec->state = REGISTRAR_ERROR_STATE;
			rec->registration_timeout = now + rec->expires - timer_interval;
			
		}
	}

	/* action successfuly completed on current list element */
	return 1; /* exit list traversal */
done:
	rec->state = INTERNAL_ERROR_STATE;
	rec->registration_timeout = now + rec->expires;
	return -1; /* exit list traversal */
}