Пример #1
0
/**
 * Add TURN Permission for a peer
 *
 * @param turnc TURN Client
 * @param peer  Peer IP-address
 * @param ph    Permission handler
 * @param arg   Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int turnc_add_perm(struct turnc *turnc, const struct sa *peer,
		   turnc_perm_h *ph, void *arg)
{
	struct perm *perm;
	int err;

	if (!turnc || !peer)
		return EINVAL;

	if (perm_find(turnc, peer))
		return 0;

	perm = mem_zalloc(sizeof(*perm), destructor);
	if (!perm)
		return ENOMEM;

	hash_append(turnc->perms, sa_hash(peer, SA_ADDR), &perm->he, perm);
	tmr_init(&perm->tmr);
	perm->peer = *peer;
	perm->turnc = turnc;
	perm->ph = ph;
	perm->arg = arg;

	err = createperm_request(perm, true);
	if (err)
		mem_deref(perm);

	return err;
}
Пример #2
0
static bool nonce_validate(char *nonce, uint32_t now, const struct sa *src)
{
	struct pl pl;
	uint32_t v;

	if (strlen(nonce) != NONCE_SIZE) {
		restund_info("auth: bad nonce length (%u)\n", strlen(nonce));
		return false;
	}

	pl.p = nonce;
	pl.l = 8;
	v = pl_x32(&pl) ^ auth.rand_time;

	if (v + auth.nonce_expiry < now) {
		restund_debug("auth: nonce expired\n");
		return false;
	}


	pl.p += 8;
	v = pl_x32(&pl) ^ auth.rand_addr;

	if (v != sa_hash(src, SA_ADDR)) {
		restund_info("auth: bad nonce src address (%j)\n", src);
		return false;
	}

	return true;
}
Пример #3
0
int  sip_keepalive_udp(struct sip_keepalive *ka, struct sip *sip,
		       struct udp_sock *us, const struct sa *paddr,
		       uint32_t interval)
{
	struct sip_udpconn *uc;

	if (!ka || !sip || !us || !paddr)
		return EINVAL;

	uc = udpconn_find(sip, us, paddr);
	if (!uc) {
		uc = mem_zalloc(sizeof(*uc), destructor);
		if (!uc)
			return ENOMEM;

		hash_append(sip->ht_udpconn, sa_hash(paddr, SA_ALL),
			    &uc->he, uc);

		uc->paddr = *paddr;
		uc->stun  = mem_ref(sip->stun);
		uc->us    = mem_ref(us);
		uc->ka_interval = interval ? interval : UDP_KEEPALIVE_INTVAL;

		/* learn mapped address immediately */
		tmr_start(&uc->tmr_ka, 0, udpconn_keepalive_handler, uc);
	}

	list_append(&uc->kal, &ka->le, ka);

	return 0;
}
Пример #4
0
static struct chan *chan_create(struct chanlist *cl, uint16_t numb,
				const struct sa *peer,
				const struct allocation *al)
{
	struct chan *chan;

	if (!cl || !peer)
		return NULL;

	chan = mem_zalloc(sizeof(*chan), destructor);
	if (!chan)
		return NULL;

	hash_append(cl->ht_numb, numb, &chan->he_numb, chan);
	hash_append(cl->ht_peer, sa_hash(peer, SA_ALL), &chan->he_peer, chan);

	chan->peer = *peer;
	chan->numb = numb;
	chan->al = al;
	chan->expires = time(NULL) + CHAN_LIFETIME;

	restund_debug("turn: allocation %p channel 0x%x %J created\n",
		      chan->al, chan->numb, &chan->peer);

	return chan;
}
Пример #5
0
static const char *mknonce(char *nonce, uint32_t now, const struct sa *src)
{
	(void)re_snprintf(nonce, NONCE_SIZE + 1, "%08x%08x",
			  auth.rand_time ^ now,
			  auth.rand_addr ^ sa_hash(src, SA_ADDR));
	return nonce;
}
Пример #6
0
struct tls_conn *tls_udp_conn(const struct tls_sock *ts, const struct sa *peer)
{
	if (!ts)
		return NULL;

	return list_ledata(hash_lookup(ts->ht_conn, sa_hash(peer, SA_ALL),
				       hash_cmp_handler, (void *)peer));
}
Пример #7
0
/** Foundation is a hash of IP address and candidate type */
static int compute_foundation(struct cand *cand)
{
	uint32_t v;

	v  = sa_hash(&cand->addr, SA_ADDR);
	v ^= cand->type;

	return re_sdprintf(&cand->foundation, "%08x", v);
}
Пример #8
0
static struct allocation *allocation_find(int proto, const struct sa *src,
					  const struct sa *dst)
{
	struct tuple tup;

	tup.cli_addr = src;
	tup.srv_addr = dst;
	tup.proto = proto;

	return list_ledata(hash_lookup(turnd.ht_alloc, sa_hash(src, SA_ALL),
				       hash_cmp_handler, &tup));
}
Пример #9
0
/** Foundation is a hash of IP address and candidate type */
static int compute_foundation(struct ice_lcand *cand,
			      const struct sa *addr, enum ice_cand_type type)
{
	uint32_t v;

	v  = sa_hash(addr, SA_ADDR);
	v ^= type;

	if (re_snprintf(cand->attr.foundation, sizeof(cand->attr.foundation),
			"%08x", v) < 0)
		return ENOMEM;

	return 0;
}
Пример #10
0
static const char *mknonce(char *nonce, time_t now, const struct sa *src)
{
	uint8_t key[MD5_SIZE];
	uint64_t nv[3];

	nv[0] = now;
	nv[1] = auth.secret;
	nv[2] = sa_hash(src, SA_ADDR);

	md5((uint8_t *)nv, sizeof(nv), key);

	(void)re_snprintf(nonce, NONCE_MAX_SIZE + 1, "%w%llx",
			  key, sizeof(key), nv[0]);

	return nonce;
}
Пример #11
0
static int send_tcp(struct dns_query *q)
{
	const struct sa *srv;
	struct tcpconn *tc;
	int err = 0;

	if (!q)
		return EINVAL;

	while (q->ntx < *q->srvc) {

		srv = &q->srvv[q->ntx++];

		DEBUG_NOTICE("trying tcp server#%u: %J\n", q->ntx-1, srv);

		tc = list_ledata(hash_lookup(q->dnsc->ht_tcpconn,
					     sa_hash(srv, SA_ALL),
					     tcpconn_cmp_handler,
					     (void *)srv));
		if (!tc) {
			err = tcpconn_alloc(&tc, q->dnsc, srv);
			if (err)
				continue;
		}

		if (tc->connected) {
			q->mb.pos = 0;
			err = tcp_send(tc->conn, &q->mb);
			if (err) {
				tcpconn_close(tc, err);
				continue;
			}

			tmr_start(&tc->tmr, tc->dnsc->conf.idle_timeout,
				  tcpconn_timeout_handler, tc);
			DEBUG_NOTICE("tcp send %J\n", srv);
		}

		list_append(&tc->ql, &q->le_tc, q);
		q->tc = mem_ref(tc);
		break;
	}

	return err;
}
Пример #12
0
static void tcp_connect_handler(const struct sa *paddr, void *arg)
{
	struct sip_transport *transp = arg;
	struct sip_conn *conn;
	int err;

	conn = mem_zalloc(sizeof(*conn), conn_destructor);
	if (!conn) {
		err = ENOMEM;
		goto out;
	}

	hash_append(transp->sip->ht_conn, sa_hash(paddr, SA_ALL),
		    &conn->he, conn);

	conn->paddr = *paddr;
	conn->sip   = transp->sip;

	err = tcp_accept(&conn->tc, transp->sock, tcp_estab_handler,
			 tcp_recv_handler, tcp_close_handler, conn);
	if (err)
		goto out;

	err = tcp_conn_local_get(conn->tc, &conn->laddr);
	if (err)
		goto out;

#ifdef USE_TLS
	if (transp->tls) {
		err = tls_start_tcp(&conn->sc, transp->tls, conn->tc, 0);
		if (err)
			goto out;
	}
#endif

	tmr_start(&conn->tmr, TCP_ACCEPT_TIMEOUT * 1000,
		  conn_tmr_handler, conn);

 out:
	if (err) {
		tcp_reject(transp->sock);
		mem_deref(conn);
	}
}
Пример #13
0
static bool allocation_status(struct le *le, void *arg)
{
	const uint32_t bsize = hash_bsize(turnd.ht_alloc);
	struct allocation *al = le->data;
	struct mbuf *mb = arg;

	(void)mbuf_printf(mb,
			  "- %04u %s/%J/%J - %J \"%s\" %us (drop %llu/%llu)\n",
			  sa_hash(&al->cli_addr, SA_ALL) & (bsize - 1),
			  net_proto2name(al->proto), &al->cli_addr,
			  &al->srv_addr, &al->rel_addr, al->username,
			  (uint32_t)tmr_get_expire(&al->tmr) / 1000,
			  al->dropc_tx, al->dropc_rx);

	perm_status(al->perms, mb);
	chan_status(al->chans, mb);

	return false;
}
Пример #14
0
static bool nonce_validate(char *nonce, time_t now, const struct sa *src)
{
	uint8_t nkey[MD5_SIZE], ckey[MD5_SIZE];
	uint64_t nv[3];
	struct pl pl;
	int64_t age;
	unsigned i;

	pl.p = nonce;
	pl.l = str_len(nonce);

	if (pl.l < NONCE_MIN_SIZE || pl.l > NONCE_MAX_SIZE) {
		restund_info("auth: bad nonce length (%zu)\n", pl.l);
		return false;
	}

	for (i=0; i<sizeof(nkey); i++) {
		nkey[i]  = ch_hex(*pl.p++) << 4;
		nkey[i] += ch_hex(*pl.p++);
		pl.l -= 2;
	}

	nv[0] = pl_x64(&pl);
	nv[1] = auth.secret;
	nv[2] = sa_hash(src, SA_ADDR);

	md5((uint8_t *)nv, sizeof(nv), ckey);

	if (memcmp(nkey, ckey, MD5_SIZE)) {
		restund_debug("auth: invalid nonce (%j)\n", src);
		return false;
	}

	age = now - nv[0];

	if (age < 0 || age > auth.nonce_expiry) {
		restund_debug("auth: nonce expired, age: %lli secs\n", age);
		return false;
	}

	return true;
}
Пример #15
0
struct chan *chan_peer_find(const struct chanlist *cl, const struct sa *peer)
{
	struct chan *chan;

	if (!cl || !peer)
		return NULL;

	chan = list_ledata(hash_lookup(cl->ht_peer, sa_hash(peer, SA_ALL),
				       hash_peer_cmp_handler, (void *)peer));
	if (!chan)
		return NULL;

	if (chan->expires < time(NULL)) {
		restund_debug("turn: allocation %p channel 0x%x %J expired\n",
			      chan->al, chan->numb, &chan->peer);
		mem_deref(chan);
		return NULL;
	}

	return chan;
}
Пример #16
0
static struct sip_conn *conn_find(struct sip *sip, const struct sa *paddr,
				  bool secure)
{
	struct le *le;

	le = list_head(hash_list(sip->ht_conn, sa_hash(paddr, SA_ALL)));

	for (; le; le = le->next) {

		struct sip_conn *conn = le->data;

		if (!secure != (conn->sc == NULL))
			continue;

		if (!sa_cmp(&conn->paddr, paddr, SA_ALL))
			continue;

		return conn;
	}

	return NULL;
}
Пример #17
0
static struct sip_udpconn *udpconn_find(struct sip *sip, struct udp_sock *us,
					const struct sa *paddr)
{
	struct le *le;

	le = list_head(hash_list(sip->ht_udpconn, sa_hash(paddr, SA_ALL)));

	for (; le; le = le->next) {

		struct sip_udpconn *uc = le->data;

		if (!sa_cmp(&uc->paddr, paddr, SA_ALL))
			continue;

		if (uc->us != us)
			continue;

		return uc;
	}

	return NULL;
}
Пример #18
0
static struct tls_conn *conn_alloc(struct tls_sock *ts, const struct sa *peer)
{
	struct tls_conn *tc;

	tc = mem_zalloc(sizeof(*tc), conn_destructor);
	if (!tc)
		return NULL;

	tc->ssl = SSL_new(ts->tls->ctx);
	if (!tc->ssl)
		goto error;

	tc->sbio_in = BIO_new(BIO_s_mem());
	if (!tc->sbio_in)
		goto error;

	tc->sbio_out = BIO_new(&bio_udp_send);
	if (!tc->sbio_out) {
		BIO_free(tc->sbio_in);
		goto error;
	}
	tc->sbio_out->ptr = tc;

	SSL_set_bio(tc->ssl, tc->sbio_in, tc->sbio_out);

	tmr_init(&tc->tmr);

	tc->peer = *peer;
	tc->ts   = ts;

	hash_append(ts->ht_conn, sa_hash(peer, SA_ALL), &tc->he, tc);

	return tc;

 error:
	return mem_deref(tc);
}
Пример #19
0
static int tcpconn_alloc(struct tcpconn **tcpp, struct dnsc *dnsc,
			 const struct sa *srv)
{
	struct tcpconn *tc;
	int err = ENOMEM;

	if (!tcpp || !dnsc || !srv)
		return EINVAL;

	tc = mem_zalloc(sizeof(struct tcpconn), tcpconn_destructor);
	if (!tc)
		goto out;

	hash_append(dnsc->ht_tcpconn, sa_hash(srv, SA_ALL), &tc->le, tc);
	tc->srv = *srv;
	tc->dnsc = dnsc;

	tc->mb = mbuf_alloc(1500);
	if (!tc->mb)
		goto out;

	err = tcp_connect(&tc->conn, srv, tcp_estab_handler,
			  tcp_recv_handler, tcp_close_handler, tc);
	if (err)
		goto out;

	tmr_start(&tc->tmr, tc->dnsc->conf.conn_timeout,
		  tcpconn_timeout_handler, tc);
 out:
	if (err)
		mem_deref(tc);
	else
		*tcpp = tc;

	return err;
}
Пример #20
0
static int conn_send(struct sip_connqent **qentp, struct sip *sip, bool secure,
		     const struct sa *dst, struct mbuf *mb,
		     sip_transp_h *transph, void *arg)
{
	struct sip_conn *conn, *new_conn = NULL;
	struct sip_connqent *qent;
	int err = 0;

	conn = conn_find(sip, dst, secure);
	if (conn) {
		if (!conn->established)
			goto enqueue;

		return tcp_send(conn->tc, mb);
	}

	new_conn = conn = mem_zalloc(sizeof(*conn), conn_destructor);
	if (!conn)
		return ENOMEM;

	hash_append(sip->ht_conn, sa_hash(dst, SA_ALL), &conn->he, conn);
	conn->paddr = *dst;
	conn->sip   = sip;

	err = tcp_connect(&conn->tc, dst, tcp_estab_handler, tcp_recv_handler,
			  tcp_close_handler, conn);
	if (err)
		goto out;

	err = tcp_conn_local_get(conn->tc, &conn->laddr);
	if (err)
		goto out;

#ifdef USE_TLS
	if (secure) {
		const struct sip_transport *transp;

		transp = transp_find(sip, SIP_TRANSP_TLS, sa_af(dst), dst);
		if (!transp || !transp->tls) {
			err = EPROTONOSUPPORT;
			goto out;
		}

		err = tls_start_tcp(&conn->sc, transp->tls, conn->tc, 0);
		if (err)
			goto out;
	}
#endif

	tmr_start(&conn->tmr, TCP_IDLE_TIMEOUT * 1000, conn_tmr_handler, conn);

 enqueue:
	qent = mem_zalloc(sizeof(*qent), qent_destructor);
	if (!qent) {
		err = ENOMEM;
		goto out;

	}

	list_append(&conn->ql, &qent->le, qent);
	qent->mb = mem_ref(mb);
	qent->transph = transph ? transph : internal_transport_handler;
	qent->arg = arg;

	if (qentp) {
		qent->qentp = qentp;
		*qentp = qent;
	}

 out:
	if (err)
		mem_deref(new_conn);

	return err;
}
Пример #21
0
static struct perm *perm_find(const struct turnc *turnc, const struct sa *peer)
{
	return list_ledata(hash_lookup(turnc->perms, sa_hash(peer, SA_ADDR),
				       hash_cmp_handler, (void *)peer));
}