Bug 1131779: 403 on permission request no longer invalidates the whole TURN relay. r=bwc

This commit is contained in:
Nils Ohlmeier [:drno] 2015-05-08 11:59:52 -07:00
parent cd5c7ebf6c
commit da58b3ed89
4 changed files with 91 additions and 14 deletions

View File

@ -60,6 +60,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "gtest/gtest.h"
#include "gtest_utils.h"
#define USE_TURN
// nICEr includes
extern "C" {
#include "nr_api.h"
@ -211,6 +213,7 @@ class TurnClient : public ::testing::Test {
void Deallocate_s() {
ASSERT_TRUE(turn_ctx_);
std::cerr << "De-Allocating..." << std::endl;
int r = nr_turn_client_deallocate(turn_ctx_);
ASSERT_EQ(0, r);
}
@ -221,6 +224,36 @@ class TurnClient : public ::testing::Test {
NS_DISPATCH_SYNC);
}
void RequestPermission_s(const std::string& target) {
nr_transport_addr addr;
int r;
// Expected pattern here is "IP4:127.0.0.1:3487"
ASSERT_EQ(0, target.compare(0, 4, "IP4:"));
size_t offset = target.rfind(':');
ASSERT_NE(std::string::npos, offset);
std::string host = target.substr(4, offset - 4);
std::string port = target.substr(offset + 1);
r = nr_ip4_str_port_to_transport_addr(host.c_str(),
atoi(port.c_str()),
IPPROTO_UDP,
&addr);
ASSERT_EQ(0, r);
r = nr_turn_client_ensure_perm(turn_ctx_, &addr);
ASSERT_EQ(0, r);
}
void RequestPermission(const std::string& target) {
RUN_ON_THREAD(test_utils->sts_target(),
WrapRunnable(this, &TurnClient::RequestPermission_s, target),
NS_DISPATCH_SYNC);
}
void Readable(NR_SOCKET s, int how, void *arg) {
// Re-arm
std::cerr << "Socket is readable" << std::endl;
@ -278,7 +311,7 @@ class TurnClient : public ::testing::Test {
}
}
void SendTo_s(const std::string& target, bool expect_success) {
void SendTo_s(const std::string& target, int expect_return) {
nr_transport_addr addr;
int r;
@ -286,7 +319,7 @@ class TurnClient : public ::testing::Test {
ASSERT_EQ(0, target.compare(0, 4, "IP4:"));
size_t offset = target.rfind(':');
ASSERT_NE(offset, std::string::npos);
ASSERT_NE(std::string::npos, offset);
std::string host = target.substr(4, offset - 4);
std::string port = target.substr(offset + 1);
@ -302,18 +335,20 @@ class TurnClient : public ::testing::Test {
test[i] = i & 0xff;
}
std::cerr << "Sending test message to " << target << " ..." << std::endl;
r = nr_turn_client_send_indication(turn_ctx_,
test, sizeof(test), 0,
&addr);
if (expect_success) {
ASSERT_EQ(0, r);
if (expect_return >= 0) {
ASSERT_EQ(expect_return, r);
}
}
void SendTo(const std::string& target, bool expect_success=true) {
void SendTo(const std::string& target, int expect_return=0) {
RUN_ON_THREAD(test_utils->sts_target(),
WrapRunnable(this, &TurnClient::SendTo_s, target,
expect_success),
expect_return),
NS_DISPATCH_SYNC);
}
@ -373,13 +408,36 @@ TEST_F(TurnClient, SendToSelfTcp) {
ASSERT_TRUE_WAIT(received() == 200, 1000);
}
TEST_F(TurnClient, PermissionDenied) {
Allocate();
RequestPermission(relay_addr_);
PR_Sleep(1000);
/* Fake a 403 response */
nr_turn_permission *perm;
perm = STAILQ_FIRST(&turn_ctx_->permissions);
ASSERT_TRUE(perm);
while (perm) {
perm->stun->last_error_code = 403;
std::cerr << "Set 403's on permission" << std::endl;
perm = STAILQ_NEXT(perm, entry);
}
SendTo(relay_addr_, R_NOT_PERMITTED);
ASSERT_TRUE(received() == 0);
//TODO: We should check if we can still send to a second destination, but
// we would need a second TURN client as one client can only handle one
// allocation (maybe as part of bug 1128128 ?).
}
TEST_F(TurnClient, DeallocateReceiveFailure) {
Allocate();
SendTo(relay_addr_);
ASSERT_TRUE_WAIT(received() == 100, 5000);
Deallocate();
turn_ctx_->state = NR_TURN_CLIENT_STATE_ALLOCATED;
SendTo(relay_addr_, true);
SendTo(relay_addr_);
PR_Sleep(1000);
ASSERT_TRUE(received() == 100);
}
@ -395,7 +453,7 @@ TEST_F(TurnClient, DeallocateReceiveFailureTcp) {
* is going to fail, which we simply ignore. Or the connection is still alive
* and we cand send the data, but it should not get forwarded to us. In either
* case we should not receive more data. */
SendTo(relay_addr_, false);
SendTo(relay_addr_, -1);
PR_Sleep(1000);
ASSERT_TRUE(received() == 100);
}

View File

@ -377,7 +377,6 @@ static void nr_ice_candidate_pair_restart(nr_ice_peer_ctx *pctx, nr_ice_cand_pai
int nr_ice_candidate_pair_start(nr_ice_peer_ctx *pctx, nr_ice_cand_pair *pair)
{
int r,_status;
UINT4 mode;
/* Register the stun ctx for when responses come in*/
if(r=nr_ice_socket_register_stun_client(pair->local->isock,pair->stun_client,&pair->stun_client_handle))

View File

@ -90,8 +90,6 @@ static int nr_turn_permission_find(nr_turn_client_ctx *ctx,
nr_transport_addr *addr,
nr_turn_permission **permp);
static int nr_turn_permission_destroy(nr_turn_permission **permp);
static int nr_turn_client_ensure_perm(nr_turn_client_ctx *ctx,
nr_transport_addr *addr);
static void nr_turn_client_refresh_cb(NR_SOCKET s, int how, void *arg);
static void nr_turn_client_permissions_cb(NR_SOCKET s, int how, void *cb);
static int nr_turn_client_send_stun_request(nr_turn_client_ctx *ctx,
@ -131,6 +129,7 @@ static int nr_turn_stun_ctx_create(nr_turn_client_ctx *tctx, int mode,
sctx->success_cb=success_cb;
sctx->error_cb=error_cb;
sctx->mode=mode;
sctx->last_error_code=0;
/* Add ourselves to the tctx's list */
STAILQ_INSERT_TAIL(&tctx->stun_ctxs, sctx, entry);
@ -207,7 +206,7 @@ static int nr_turn_stun_ctx_start(nr_turn_stun_ctx *ctx)
if ((r=nr_stun_client_reset(ctx->stun))) {
r_log(NR_LOG_TURN, LOG_ERR, "TURN(%s): Couldn't reset STUN",
ctx->tctx->label);
tctx->label);
ABORT(r);
}
@ -227,6 +226,8 @@ static void nr_turn_stun_ctx_cb(NR_SOCKET s, int how, void *arg)
int r, _status;
nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
ctx->last_error_code = ctx->stun->error_code;
switch (ctx->stun->state) {
case NR_STUN_CLIENT_STATE_DONE:
/* Save the realm and nonce */
@ -597,6 +598,19 @@ static void nr_turn_client_error_cb(NR_SOCKET s, int how, void *arg)
nr_turn_client_failed(ctx->tctx);
}
static void nr_turn_client_permission_error_cb(NR_SOCKET s, int how, void *arg)
{
nr_turn_stun_ctx *ctx = (nr_turn_stun_ctx *)arg;
if (ctx->last_error_code == 403) {
r_log(NR_LOG_TURN, LOG_WARNING, "TURN(%s): mode %d, permission denied",
ctx->tctx->label, ctx->mode);
} else{
nr_turn_client_error_cb(0, 0, ctx);
}
}
int nr_turn_client_allocate(nr_turn_client_ctx *ctx,
NR_async_cb finished_cb, void *cb_arg)
{
@ -889,7 +903,7 @@ abort:
unused.
*/
static int nr_turn_client_ensure_perm(nr_turn_client_ctx *ctx, nr_transport_addr *addr)
int nr_turn_client_ensure_perm(nr_turn_client_ctx *ctx, nr_transport_addr *addr)
{
int r, _status;
nr_turn_permission *perm = 0;
@ -949,7 +963,7 @@ static int nr_turn_permission_create(nr_turn_client_ctx *ctx, nr_transport_addr
if ((r=nr_turn_stun_ctx_create(ctx, NR_TURN_CLIENT_MODE_PERMISSION_REQUEST,
nr_turn_client_permissions_cb,
nr_turn_client_error_cb,
nr_turn_client_permission_error_cb,
&perm->stun)))
ABORT(r);
@ -991,6 +1005,9 @@ static int nr_turn_permission_find(nr_turn_client_ctx *ctx, nr_transport_addr *a
if (!perm) {
ABORT(R_NOT_FOUND);
}
if (perm->stun->last_error_code == 403) {
ABORT(R_NOT_PERMITTED);
}
*permp = perm;
_status=0;

View File

@ -52,6 +52,7 @@ typedef struct nr_turn_stun_ctx_ {
char *realm;
NR_async_cb success_cb;
NR_async_cb error_cb;
int last_error_code;
STAILQ_ENTRY(nr_turn_stun_ctx_) entry;
} nr_turn_stun_ctx;
@ -129,5 +130,7 @@ int nr_turn_client_parse_data_indication(nr_turn_client_ctx *ctx,
UCHAR *newmsg, size_t *newlen,
size_t newsize,
nr_transport_addr *remote_addr);
int nr_turn_client_ensure_perm(nr_turn_client_ctx *ctx,
nr_transport_addr *addr);
#endif