예제 #1
0
파일: auth.c 프로젝트: AmesianX/restund
static int module_close(void)
{
	restund_stun_unregister_handler(&stun);

	restund_debug("auth: module closed\n");

	return 0;
}
예제 #2
0
static int module_init(void)
{
	restund_db_set_auth_handler(auth_handler);

	restund_debug("restauth: module loaded\n");

	return 0;
}
예제 #3
0
static int module_close(void)
{
	restund_db_set_auth_handler(NULL);

	restund_debug("restauth: module closed\n");

	return 0;
}
예제 #4
0
static int module_close(void)
{
	mysql_close(&my.mysql);

	restund_debug("mysql: module closed\n");

	return 0;
}
예제 #5
0
파일: status.c 프로젝트: AmesianX/restund
static int module_close(void)
{
	stg.us = mem_deref(stg.us);
	stg.httpd = mem_deref(stg.httpd);

	restund_debug("status: module closed\n");

	return 0;
}
예제 #6
0
static void destructor(void *arg)
{
	struct chan *chan = arg;

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

	hash_unlink(&chan->he_numb);
	hash_unlink(&chan->he_peer);
}
예제 #7
0
파일: auth.c 프로젝트: AmesianX/restund
/* shared secret authentication as described in 
 * http://tools.ietf.org/html/draft-uberti-rtcweb-turn-rest-00
 */
static bool sharedsecret_auth_check_timestamp(const struct stun_attr *user, const time_t now) 
{
    long ts = 0;
    sscanf(user->v.username, "%ld:%*s", &ts);
    if (now > ts) {
        restund_debug("auth: shared secret nonce expired, ts was %ld now is %ld\n", ts, now);
        return false;
    }
    return true;
}
예제 #8
0
static void chan_refresh(struct chan *chan)
{
	if (!chan)
		return;

	chan->expires = time(NULL) + CHAN_LIFETIME;

	restund_debug("turn: allocation %p channel 0x%x %J refreshed\n",
		      chan->al, chan->numb, &chan->peer);
}
예제 #9
0
파일: auth.c 프로젝트: AmesianX/restund
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;
}
예제 #10
0
파일: turn.c 프로젝트: AmesianX/restund
static int module_close(void)
{
	hash_flush(turnd.ht_alloc);
	turnd.ht_alloc = mem_deref(turnd.ht_alloc);
	restund_cmd_unsubscribe(&cmd_turnstats);
	restund_cmd_unsubscribe(&cmd_turn);
	restund_stun_unregister_handler(&stun);

	restund_debug("turn: module closed\n");

	return 0;
}
예제 #11
0
static int myconnect(void)
{
	mysql_init(&my.mysql);

	if (!mysql_real_connect(&my.mysql, my.host, my.user, my.pass, my.db,
				0, NULL, 0))
		return(ECONNREFUSED);

	restund_debug("mysql: connected (server %s at %s)\n",
		      mysql_get_server_info(&my.mysql),
		      mysql_get_host_info(&my.mysql));

	return 0;
}
예제 #12
0
static int module_init(void)
{
	auth.nonce_expiry = NONCE_EXPIRY;
	auth.rand_time = rand_u32();
	auth.rand_addr = rand_u32();

	conf_get_u32(restund_conf(), "auth_nonce_expiry", &auth.nonce_expiry);

	restund_stun_register_handler(&stun);

	restund_debug("auth: module loaded (nonce_expiry=%us)\n",
		      auth.nonce_expiry);

	return 0;
}
예제 #13
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;
}
예제 #14
0
struct chan *chan_numb_find(const struct chanlist *cl, uint16_t numb)
{
	struct chan *chan;

	if (!cl)
		return NULL;

	chan = list_ledata(hash_lookup(cl->ht_numb, numb,
				       hash_numb_cmp_handler, &numb));
	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;
}
예제 #15
0
static int listen_handler(const struct pl *addrport, void *arg)
{
    uint32_t sockbuf_size = *(uint32_t *)arg;
    struct udp_lstnr *ul = NULL;
    int err = ENOMEM;

    ul = mem_zalloc(sizeof(*ul), destructor);
    if (!ul) {
        restund_warning("udp listen error: %s\n", strerror(err));
        goto out;
    }

    list_append(&lstnrl, &ul->le, ul);

    err = sa_decode(&ul->bnd_addr, addrport->p, addrport->l);
    if (err || sa_is_any(&ul->bnd_addr) || !sa_port(&ul->bnd_addr)) {
        restund_warning("bad udp_listen directive: '%r'\n", addrport);
        err = EINVAL;
        goto out;
    }

    err = udp_listen(&ul->us, &ul->bnd_addr, udp_recv, ul);
    if (err) {
        restund_warning("udp listen %J: %s\n", &ul->bnd_addr,
                        strerror(err));
        goto out;
    }

    if (sockbuf_size > 0)
        (void)udp_sockbuf_set(ul->us, sockbuf_size);

    restund_debug("udp listen: %J\n", &ul->bnd_addr);

out:
    if (err)
        mem_deref(ul);

    return err;
}
예제 #16
0
static int auth_handler(const char *user, uint8_t *ha1)
{
	uint8_t key[MD5_SIZE], digest[SHA_DIGEST_LENGTH];
	const char *username;
	time_t expires, now;
	char pass[28];
	size_t len;
	int err;

	err = decode_user(&expires, &username, user);
	if (err)
		return err;

	now = time(NULL);

	if (expires < now) {
		restund_debug("restauth: user '%s' expired %lli seconds ago\n",
			      user, now - expires);
		return ETIMEDOUT;
	}

	/* avoid recursive loops */
	restund_db_set_auth_handler(NULL);
	err = restund_get_ha1(username, key);
	restund_db_set_auth_handler(auth_handler);
	if (err)
		return err;

	hmac_sha1(key, sizeof(key),
		  (uint8_t *)user, strlen(user),
		  digest, sizeof(digest));

	len = sizeof(pass);
	err = base64_encode(digest, sizeof(digest), pass, &len);
	if (err)
		return err;

	return md5_printf(ha1, "%s:%s:%b", user, restund_realm(), pass, len);
}
예제 #17
0
파일: turn.c 프로젝트: AmesianX/restund
static int module_init(void)
{
	uint32_t x, bsize = ALLOC_DEFAULT_BSIZE;
	struct pl opt;
	int err = 0;

	restund_stun_register_handler(&stun);
	restund_cmd_subscribe(&cmd_turn);
	restund_cmd_subscribe(&cmd_turnstats);

	/* turn_external_addr */
	if (!conf_get(restund_conf(), "turn_relay_addr", &opt))
		err = sa_set(&turnd.rel_addr, &opt, 0);
	else
		sa_init(&turnd.rel_addr, AF_UNSPEC);

	if (err) {
		restund_error("turn: bad turn_relay_addr: '%r'\n", &opt);
		goto out;
	}

	/* turn_external_addr6 */
	if (!conf_get(restund_conf(), "turn_relay_addr6", &opt))
		err = sa_set(&turnd.rel_addr6, &opt, 0);
	else
		sa_init(&turnd.rel_addr6, AF_UNSPEC);

	if (err) {
		restund_error("turn: bad turn_relay_addr6: '%r'\n", &opt);
		goto out;
	}

	if (!sa_isset(&turnd.rel_addr, SA_ADDR) &&
	    !sa_isset(&turnd.rel_addr6, SA_ADDR)) {
		restund_error("turn: no relay address configured\n");
		err = EINVAL;
		goto out;
	}

	/* turn_max_lifetime, turn_max_allocations, udp_sockbuf_size */
	turnd.lifetime_max = TURN_DEFAULT_LIFETIME;
	conf_get_u32(restund_conf(), "turn_max_lifetime", &turnd.lifetime_max);
	conf_get_u32(restund_conf(), "turn_max_allocations", &bsize);
	conf_get_u32(restund_conf(), "udp_sockbuf_size",
		     &turnd.udp_sockbuf_size);

	for (x=2; (uint32_t)1<<x<bsize; x++);
	bsize = 1<<x;

	err = hash_alloc(&turnd.ht_alloc, bsize);
	if (err) {
		restund_error("turnd hash alloc error: %m\n", err);
		goto out;
	}

	restund_debug("turn: lifetime=%u ext=%j ext6=%j bsz=%u\n",
		      turnd.lifetime_max, &turnd.rel_addr, &turnd.rel_addr6,
		      bsize);

 out:
	return err;
}
예제 #18
0
파일: turn.c 프로젝트: AmesianX/restund
static bool request_handler(struct restund_msgctx *ctx, int proto, void *sock,
			    const struct sa *src, const struct sa *dst,
			    const struct stun_msg *msg)
{
	const uint16_t met = stun_msg_method(msg);
	struct allocation *al;
	int err = 0;

	switch (met) {

	case STUN_METHOD_ALLOCATE:
	case STUN_METHOD_REFRESH:
	case STUN_METHOD_CREATEPERM:
	case STUN_METHOD_CHANBIND:
		break;

	default:
		return false;
	}

	if (ctx->ua.typec > 0) {
		err = stun_ereply(proto, sock, src, 0, msg,
				  420, "Unknown Attribute",
				  ctx->key, ctx->keylen, ctx->fp, 2,
				  STUN_ATTR_UNKNOWN_ATTR, &ctx->ua,
				  STUN_ATTR_SOFTWARE, restund_software);
		goto out;
	}

	al = allocation_find(proto, src, dst);

	if (!al && met != STUN_METHOD_ALLOCATE) {
		restund_debug("turn: allocation does not exist\n");
		err = stun_ereply(proto, sock, src, 0, msg,
				  437, "Allocation Mismatch",
				  ctx->key, ctx->keylen, ctx->fp, 1,
				  STUN_ATTR_SOFTWARE, restund_software);
		goto out;
	}

	if (al && al->username && ctx->key) {

		struct stun_attr *usr = stun_msg_attr(msg, STUN_ATTR_USERNAME);

		if (!usr || strcmp(usr->v.username, al->username)) {
			restund_debug("turn: wrong credetials\n");
			err = stun_ereply(proto, sock, src, 0, msg,
					  441, "Wrong Credentials",
					  ctx->key, ctx->keylen, ctx->fp, 1,
					  STUN_ATTR_SOFTWARE,restund_software);
			goto out;
		}
	}

	switch (met) {

	case STUN_METHOD_ALLOCATE:
		allocate_request(&turnd, al, ctx, proto, sock, src, dst, msg);
		break;

	case STUN_METHOD_REFRESH:
		refresh_request(&turnd, al, ctx, proto, sock, src, msg);
		break;

	case STUN_METHOD_CREATEPERM:
		createperm_request(al, ctx, proto, sock, src, msg);
		break;

	case STUN_METHOD_CHANBIND:
		chanbind_request(al, ctx, proto, sock, src, msg);
		break;
	}

 out:
	if (err) {
		restund_warning("turn reply error: %m\n", err);
	}

	return true;
}