コード例 #1
0
ファイル: stun.c プロジェクト: Archipov/android-client
/* Decode and authenticate message with unknown non-mandatory attribute */
static int handle_unknown_non_mandatory(void)
{
    pj_pool_t *pool = pj_pool_create(mem, NULL, 1000, 1000, NULL);
    pj_stun_msg *msg0, *msg1, *msg2;
    pj_uint8_t data[] = { 1, 2, 3, 4, 5, 6};
    pj_uint8_t packet[500];
    pj_stun_auth_cred cred;
    pj_size_t len;
    pj_status_t rc;

    PJ_LOG(3,(THIS_FILE, "  handling unknown non-mandatory attr"));

    PJ_LOG(3,(THIS_FILE, "    encoding"));
    rc = pj_stun_msg_create(pool, PJ_STUN_BINDING_REQUEST, PJ_STUN_MAGIC, NULL, &msg0);
    rc += pj_stun_msg_add_string_attr(pool, msg0, PJ_STUN_ATTR_USERNAME, &USERNAME);
    rc += pj_stun_msg_add_binary_attr(pool, msg0, 0x80ff, data, sizeof(data));
    rc += pj_stun_msg_add_msgint_attr(pool, msg0);
    rc += pj_stun_msg_encode(msg0, packet, sizeof(packet), 0, &PASSWORD, &len);

#if 0
    if (1) {
	unsigned i;
	puts("");
	printf("{ ");
	for (i=0; i<len; ++i) printf("0x%02x, ", packet[i]);
	puts(" }");
    }
#endif

    PJ_LOG(3,(THIS_FILE, "    decoding"));
    rc += pj_stun_msg_decode(pool, packet, len, PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET,
			     &msg1, NULL, NULL);

    rc += cmp_msg(msg0, msg1);

    pj_bzero(&cred, sizeof(cred));
    cred.type = PJ_STUN_AUTH_CRED_STATIC;
    cred.data.static_cred.username = USERNAME;
    cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
    cred.data.static_cred.data = PASSWORD;

    PJ_LOG(3,(THIS_FILE, "    authenticating"));
    rc += pj_stun_authenticate_request(packet, (unsigned)len, msg1, &cred, pool, 
				       NULL, NULL);

    PJ_LOG(3,(THIS_FILE, "    clone"));
    msg2 = pj_stun_msg_clone(pool, msg1);
    rc += cmp_msg(msg0, msg2);

    pj_pool_release(pool);

    return rc==0 ? 0 : -4410;
}
コード例 #2
0
static pj_stun_msg* create_msgint3(pj_pool_t *pool, test_vector *v)
{
    pj_stun_msg *msg;
    pj_sockaddr mapped_addr;
    pj_str_t s1;
    pj_status_t status;

    status = pj_stun_msg_create(pool, v->msg_type, PJ_STUN_MAGIC,
				(pj_uint8_t*)v->tsx_id, &msg);
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SOFTWARE, 
					 pj_cstr(&s1, "test vector"));
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_sockaddr_init(pj_AF_INET6(), &mapped_addr,
		      pj_cstr(&s1, "2001:db8:1234:5678:11:2233:4455:6677"),
		      32853);
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_stun_msg_add_sockaddr_attr(pool, msg, 
					   PJ_STUN_ATTR_XOR_MAPPED_ADDR,
					   PJ_TRUE, &mapped_addr, 
					   sizeof(pj_sockaddr));
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_stun_msg_add_msgint_attr(pool, msg);
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_stun_msg_add_uint_attr(pool, msg, PJ_STUN_ATTR_FINGERPRINT, 0);
    if (status != PJ_SUCCESS)
	goto on_error;

    return msg;

on_error:
    app_perror("    error: create_msgint3()", status);
    return NULL;
}
コード例 #3
0
static pj_stun_msg* create_msgint1(pj_pool_t *pool, test_vector *v)
{
    pj_stun_msg *msg;
    pj_timestamp u64;
    pj_str_t s1;
    pj_status_t status;

    status = pj_stun_msg_create(pool, v->msg_type, PJ_STUN_MAGIC,
				(pj_uint8_t*)v->tsx_id, &msg);
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_stun_msg_add_uint_attr(pool, msg, PJ_STUN_ATTR_PRIORITY, 
				       0x6e0001ff);
    if (status != PJ_SUCCESS)
	goto on_error;

    u64.u32.hi = 0x932ff9b1;
    u64.u32.lo = 0x51263b36;
    status = pj_stun_msg_add_uint64_attr(pool, msg, 
					 PJ_STUN_ATTR_ICE_CONTROLLED, &u64);
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_USERNAME, 
					 pj_cstr(&s1, v->username));
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_stun_msg_add_msgint_attr(pool, msg);
    if (status != PJ_SUCCESS)
	goto on_error;

    status = pj_stun_msg_add_uint_attr(pool, msg, PJ_STUN_ATTR_FINGERPRINT, 0);
    if (status != PJ_SUCCESS)
	goto on_error;

    return msg;

on_error:
    app_perror("    error: create_msgint1()", status);
    return NULL;
}
コード例 #4
0
static pj_stun_msg* create_msgint2(pj_pool_t *pool, test_vector *v)
{
    pj_stun_msg *msg;
    pj_sockaddr_in mapped_addr;
    pj_str_t s1;

    pj_stun_msg_create(pool, v->msg_type, PJ_STUN_MAGIC,
		       (pj_uint8_t*)v->tsx_id, &msg);

    pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SOFTWARE, 
				pj_cstr(&s1, "test vector"));

    pj_sockaddr_in_init(&mapped_addr, pj_cstr(&s1, "127.0.0.1"), 32853);
    pj_stun_msg_add_sockaddr_attr(pool, msg, PJ_STUN_ATTR_XOR_MAPPED_ADDR,
				  PJ_TRUE, &mapped_addr, 
				  sizeof(pj_sockaddr_in));

    pj_stun_msg_add_msgint_attr(pool, msg);
    pj_stun_msg_add_uint_attr(pool, msg, PJ_STUN_ATTR_FINGERPRINT, 0);

    return msg;
}
コード例 #5
0
ファイル: server.c プロジェクト: kaaustubh/pjsip
static pj_stun_msg* create_success_response(test_server *test_srv,
					    turn_allocation *alloc,
					    pj_stun_msg *req,
					    pj_pool_t *pool,
					    unsigned lifetime,
					    pj_str_t *auth_key)
{
    pj_stun_msg *resp;
    pj_str_t tmp;
    pj_status_t status;

    /* Create response */
    status = pj_stun_msg_create_response(pool, req, 0, NULL, &resp);
    if (status != PJ_SUCCESS) {
	return NULL;
    }
    /* Add TURN_NONCE */
    pj_stun_msg_add_string_attr(pool, resp, PJ_STUN_ATTR_NONCE, pj_cstr(&tmp, TURN_NONCE));
    /* Add LIFETIME */
    pj_stun_msg_add_uint_attr(pool, resp, PJ_STUN_ATTR_LIFETIME, lifetime);
    if (lifetime != 0) {
	/* Add XOR-RELAYED-ADDRESS */
	pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_XOR_RELAYED_ADDR, PJ_TRUE, &alloc->alloc_addr,
				      pj_sockaddr_get_len(&alloc->alloc_addr));
	/* Add XOR-MAPPED-ADDRESS */
	pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, &alloc->client_addr,
				      pj_sockaddr_get_len(&alloc->client_addr));
    }

    /* Add blank MESSAGE-INTEGRITY */
    pj_stun_msg_add_msgint_attr(pool, resp);

    /* Set auth key */
    pj_stun_create_key(pool, auth_key, &test_srv->domain, &test_srv->username,
		       PJ_STUN_PASSWD_PLAIN, &test_srv->passwd);

    return resp;
}
コード例 #6
0
static pj_stun_msg* create_msgint1(pj_pool_t *pool, test_vector *v)
{
    pj_stun_msg *msg;
    pj_timestamp u64;
    pj_str_t s1;

    pj_stun_msg_create(pool, v->msg_type, PJ_STUN_MAGIC,
		       (pj_uint8_t*)v->tsx_id, &msg);

    pj_stun_msg_add_uint_attr(pool, msg, PJ_STUN_ATTR_PRIORITY, 0x6e0001ff);
    u64.u32.hi = 0x932ff9b1;
    u64.u32.lo = 0x51263b36;
    pj_stun_msg_add_uint64_attr(pool, msg, PJ_STUN_ATTR_ICE_CONTROLLED,
				&u64);

    pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_USERNAME, 
				pj_cstr(&s1, v->username));

    pj_stun_msg_add_msgint_attr(pool, msg);

    pj_stun_msg_add_uint_attr(pool, msg, PJ_STUN_ATTR_FINGERPRINT, 0);

    return msg;
}
コード例 #7
0
ファイル: sess_auth.c プロジェクト: Antares84/asuswrt-merlin
static int run_client_test(const char *title,

			   pj_bool_t server_responding,
			   pj_stun_auth_type server_auth_type,

			   pj_stun_auth_type client_auth_type,
			   const char *realm,
			   const char *username,
			   const char *nonce,
			   const char *password,
			   pj_bool_t dummy_mi,

			   pj_bool_t expected_error,
			   pj_status_t expected_code,
			   const char *expected_realm,
			   const char *expected_nonce,
			   
			   int (*more_check)(void))
{
    pj_pool_t *pool;
    pj_stun_session_cb sess_cb;
    pj_stun_auth_cred cred;
    pj_stun_tx_data *tdata;
    pj_status_t status;
    int rc = 0;
    
    PJ_LOG(3,(THIS_FILE, "   %s test", title));

    /* Create client */
    pool = pj_pool_create(mem, "client", 1000, 1000, NULL);
    client = PJ_POOL_ZALLOC_T(pool, struct client);
    client->pool = pool;
    client->responding = PJ_TRUE;

    /* Create STUN session */
    pj_bzero(&sess_cb, sizeof(sess_cb));
    sess_cb.on_request_complete = &client_on_request_complete;
    sess_cb.on_send_msg = &client_send_msg;
    status = pj_stun_session_create(&stun_cfg, "client", &sess_cb, PJ_FALSE, NULL, &client->sess);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -200;
    }

    /* Create semaphore */
    status = pj_sem_create(pool, "client", 0, 1, &client->test_complete);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -205;
    }

    /* Create client socket */
    status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &client->sock);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -210;
    }

    /* Bind client socket */
    status = pj_sock_bind_in(client->sock, 0, 0);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -220;
    }

    /* Create client thread */
    status = pj_thread_create(pool, "client", &client_thread, NULL, 0, 0, &client->thread);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -230;
    }

    /* Initialize credential */
    pj_bzero(&cred, sizeof(cred));
    cred.type = PJ_STUN_AUTH_CRED_STATIC;
    if (realm) cred.data.static_cred.realm = pj_str((char*)realm);
    if (username) cred.data.static_cred.username = pj_str((char*)username);
    if (nonce) cred.data.static_cred.nonce = pj_str((char*)nonce);
    if (password) cred.data.static_cred.data = pj_str((char*)password);
    cred.data.static_cred.data_type = PJ_STUN_PASSWD_PLAIN;
    status = pj_stun_session_set_credential(client->sess, client_auth_type, &cred);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -240;
    }

    /* Create the server */
    status = create_std_server(server_auth_type, server_responding);
    if (status != 0) {
	destroy_client_server();
	return status;
    }

    /* Create request */
    status = pj_stun_session_create_req(client->sess, PJ_STUN_BINDING_REQUEST, 
					PJ_STUN_MAGIC, NULL, &tdata);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -250;
    }

    /* Add our own attributes if client authentication is set to none */
    if (client_auth_type == PJ_STUN_AUTH_NONE) {
	pj_str_t tmp;
	if (realm)
	    pj_stun_msg_add_string_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_REALM, pj_cstr(&tmp, realm));
	if (username)
	    pj_stun_msg_add_string_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_USERNAME, pj_cstr(&tmp, username));
	if (nonce)
	    pj_stun_msg_add_string_attr(tdata->pool, tdata->msg, PJ_STUN_ATTR_NONCE, pj_cstr(&tmp, nonce));
	if (password) {
	    // ignored
	}
	if (dummy_mi) {
	    pj_stun_msgint_attr *mi;

	    pj_stun_msgint_attr_create(tdata->pool, &mi);
	    pj_stun_msg_add_attr(tdata->msg, &mi->hdr);
	}
	   
    }

    /* Send the request */
    status = pj_stun_session_send_msg(client->sess, NULL, PJ_FALSE, PJ_TRUE, &server->addr,
				      pj_sockaddr_get_len(&server->addr), tdata);
    if (status != PJ_SUCCESS) {
	destroy_client_server();
	return -270;
    }

    /* Wait until test complete */
    pj_sem_wait(client->test_complete);


    /* Verify response */
    if (expected_error) {
	if (expected_code != client->response_status) {
	    char e1[PJ_ERR_MSG_SIZE], e2[PJ_ERR_MSG_SIZE];

	    pj_strerror(expected_code, e1, sizeof(e1));
	    pj_strerror(client->response_status, e2, sizeof(e2));

	    PJ_LOG(3,(THIS_FILE, "    err: expecting %d (%s) but got %d (%s) response",
		      expected_code, e1, client->response_status, e2));
	    rc = -500;
	} 

    } else {
	int res_code = 0;
	pj_stun_realm_attr *arealm;
	pj_stun_nonce_attr *anonce;

	if (client->response_status != 0) {
	    PJ_LOG(3,(THIS_FILE, "    err: expecting successful operation but got error %d", 
		      client->response_status));
	    rc = -600;
	    goto done;
	} 

	if (PJ_STUN_IS_ERROR_RESPONSE(client->response->hdr.type)) {
	    pj_stun_errcode_attr *aerr = NULL;

	    aerr = (pj_stun_errcode_attr*)
		   pj_stun_msg_find_attr(client->response, 
					 PJ_STUN_ATTR_ERROR_CODE, 0);
	    if (aerr == NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: received error response without ERROR-CODE"));
		rc = -610;
		goto done;
	    }

	    res_code = aerr->err_code;
	} else {
	    res_code = 0;
	}

	/* Check that code matches */
	if (expected_code != res_code) {
	    PJ_LOG(3,(THIS_FILE, "    err: expecting response code %d but got %d",
		      expected_code, res_code));
	    rc = -620;
	    goto done;
	}

	/* Find REALM and NONCE attributes */
	arealm = (pj_stun_realm_attr*)
	         pj_stun_msg_find_attr(client->response, PJ_STUN_ATTR_REALM, 0);
	anonce = (pj_stun_nonce_attr*)
	         pj_stun_msg_find_attr(client->response, PJ_STUN_ATTR_NONCE, 0);

	if (expected_realm) {
	    if (arealm == NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: expecting REALM in esponse"));
		rc = -630;
		goto done;
	    }
	    if (pj_strcmp2(&arealm->value, expected_realm)!=0) {
		PJ_LOG(3,(THIS_FILE, "    err: REALM mismatch in response"));
		rc = -640;
		goto done;
	    }
	} else {
	    if (arealm != NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: non expecting REALM in response"));
		rc = -650;
		goto done;
	    }
	}

	if (expected_nonce) {
	    if (anonce == NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: expecting NONCE in esponse"));
		rc = -660;
		goto done;
	    }
	    if (pj_strcmp2(&anonce->value, expected_nonce)!=0) {
		PJ_LOG(3,(THIS_FILE, "    err: NONCE mismatch in response"));
		rc = -670;
		goto done;
	    }
	} else {
	    if (anonce != NULL) {
		PJ_LOG(3,(THIS_FILE, "    err: non expecting NONCE in response"));
		rc = -680;
		goto done;
	    }
	}
    }

    /* Our tests are okay so far. Let caller do some more tests if
     * it wants to.
     */
    if (rc==0 && more_check) {
	rc = (*more_check)();
    }


done:
    destroy_client_server();
    return rc;
}
コード例 #8
0
ファイル: server.c プロジェクト: kaaustubh/pjsip
static pj_bool_t turn_on_data_recvfrom(pj_activesock_t *asock,
				       void *data,
				       pj_size_t size,
				       const pj_sockaddr_t *src_addr,
				       int addr_len,
				       pj_status_t status)
{
    test_server *test_srv;
    pj_pool_t *pool;
    turn_allocation *alloc;
    pj_stun_msg *req, *resp = NULL;
    pj_str_t auth_key = { NULL, 0 };
    char client_info[PJ_INET6_ADDRSTRLEN+10];
    unsigned i;
    pj_ssize_t len;

    if (status != PJ_SUCCESS)
	return PJ_TRUE;

    pj_sockaddr_print(src_addr, client_info, sizeof(client_info), 3);

    test_srv = (test_server*) pj_activesock_get_user_data(asock);
    pool = pj_pool_create(test_srv->stun_cfg->pf, NULL, 512, 512, NULL);

    /* Find the client */
    for (i=0; i<test_srv->turn_alloc_cnt; i++) {
	if (pj_sockaddr_cmp(&test_srv->turn_alloc[i].client_addr, src_addr)==0)
	    break;
    }


    if (pj_stun_msg_check((pj_uint8_t*)data, size, PJ_STUN_NO_FINGERPRINT_CHECK)!=PJ_SUCCESS)  {
	/* Not STUN message, this probably is a ChannelData */
	pj_turn_channel_data cd;
	const pj_turn_channel_data *pcd = (const pj_turn_channel_data*)data;
	pj_ssize_t sent;

	if (i==test_srv->turn_alloc_cnt) {
	    /* Invalid data */
	    PJ_LOG(1,(THIS_FILE, 
		      "TURN Server received strayed data"));
	    goto on_return;
	}

	alloc = &test_srv->turn_alloc[i];

	cd.ch_number = pj_ntohs(pcd->ch_number);
	cd.length = pj_ntohs(pcd->length);

	/* For UDP check the packet length */
	if (size < cd.length+sizeof(cd)) {
	    PJ_LOG(1,(THIS_FILE, 
		      "TURN Server: ChannelData discarded: UDP size error"));
	    goto on_return;
	}

	/* Lookup peer */
	for (i=0; i<alloc->perm_cnt; ++i) {
	    if (alloc->chnum[i] == cd.ch_number)
		break;
	}

	if (i==alloc->perm_cnt) {
	    PJ_LOG(1,(THIS_FILE, 
		      "TURN Server: ChannelData discarded: invalid channel number"));
	    goto on_return;
	}

	/* Relay the data to peer */
	sent = cd.length;
	pj_activesock_sendto(alloc->sock, &alloc->send_key,
			     pcd+1, &sent, 0,
			     &alloc->perm[i],
			     pj_sockaddr_get_len(&alloc->perm[i]));

	/* Done */
	goto on_return;
    }

    status = pj_stun_msg_decode(pool, (pj_uint8_t*)data, size, 
				PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET |
				    PJ_STUN_NO_FINGERPRINT_CHECK, 
				&req, NULL, NULL);
    if (status != PJ_SUCCESS) {
	char errmsg[PJ_ERR_MSG_SIZE];
	pj_strerror(status, errmsg, sizeof(errmsg));
	PJ_LOG(1,("", "STUN message decode error from client %s: %s", client_info, errmsg));
	goto on_return;
    }

    if (i==test_srv->turn_alloc_cnt) {
	/* New client */
	//pj_str_t ip_addr;
	pj_stun_username_attr *uname;
	pj_activesock_cb alloc_sock_cb;
	turn_allocation *alloc;

	/* Must be Allocate request */
	if (req->hdr.type != PJ_STUN_ALLOCATE_REQUEST) {
	    PJ_LOG(1,(THIS_FILE, "Invalid %s %s from client %s",
		      pj_stun_get_method_name(req->hdr.type),
		      pj_stun_get_class_name(req->hdr.type),
		      client_info));

	    if (PJ_STUN_IS_REQUEST(req->hdr.type))
		pj_stun_msg_create_response(pool, req, PJ_STUN_SC_BAD_REQUEST, NULL, &resp);
	    goto send_pkt;
	}

	test_srv->turn_stat.rx_allocate_cnt++;

	/* Skip if we're not responding to Allocate request */
	if (!test_srv->turn_respond_allocate)
	    return PJ_TRUE;

	/* Check if we have too many clients */
	if (test_srv->turn_alloc_cnt == MAX_TURN_ALLOC) {
	    pj_stun_msg_create_response(pool, req, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL, &resp);
	    goto send_pkt;
	}

	/* Get USERNAME attribute */
	uname = (pj_stun_username_attr*)
		pj_stun_msg_find_attr(req, PJ_STUN_ATTR_USERNAME, 0);

	/* Reject if it doesn't have MESSAGE-INTEGRITY or USERNAME attributes or
	 * the user is incorrect
	 */
	if (pj_stun_msg_find_attr(req, PJ_STUN_ATTR_MESSAGE_INTEGRITY, 0) == NULL ||
	    uname==NULL || pj_stricmp2(&uname->value, TURN_USERNAME) != 0) 
	{
	    pj_str_t tmp;

	    pj_stun_msg_create_response(pool, req, PJ_STUN_SC_UNAUTHORIZED, NULL, &resp);
	    pj_stun_msg_add_string_attr(pool, resp, PJ_STUN_ATTR_REALM, &test_srv->domain);
	    pj_stun_msg_add_string_attr(pool, resp, PJ_STUN_ATTR_NONCE, pj_cstr(&tmp, TURN_NONCE));
	    goto send_pkt;
	}

	pj_bzero(&alloc_sock_cb, sizeof(alloc_sock_cb));
	alloc_sock_cb.on_data_recvfrom = &alloc_on_data_recvfrom;

	/* Create allocation */
	alloc = &test_srv->turn_alloc[test_srv->turn_alloc_cnt];
	alloc->perm_cnt = 0;
	alloc->test_srv = test_srv;
	pj_memcpy(&alloc->client_addr, src_addr, addr_len);
	pj_ioqueue_op_key_init(&alloc->send_key, sizeof(alloc->send_key));

	alloc->pool = pj_pool_create(test_srv->stun_cfg->pf, "alloc", 512, 512, NULL);

	/* Create relay socket */
	pj_sockaddr_in_init(&alloc->alloc_addr.ipv4, NULL, 0);
	pj_gethostip(pj_AF_INET(), &alloc->alloc_addr);

	status = pj_activesock_create_udp(alloc->pool, &alloc->alloc_addr, NULL, 
					  test_srv->stun_cfg->ioqueue,
					  &alloc_sock_cb, alloc, 
					  &alloc->sock, &alloc->alloc_addr);
	if (status != PJ_SUCCESS) {
	    pj_pool_release(alloc->pool);
	    pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp);
	    goto send_pkt;
	}
	//pj_sockaddr_set_str_addr(pj_AF_INET(), &alloc->alloc_addr, &ip_addr);

	pj_activesock_set_user_data(alloc->sock, alloc);

	status = pj_activesock_start_recvfrom(alloc->sock, alloc->pool, 1500, 0);
	if (status != PJ_SUCCESS) {
	    pj_activesock_close(alloc->sock);
	    pj_pool_release(alloc->pool);
	    pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp);
	    goto send_pkt;
	}

	/* Create Data indication */
	status = pj_stun_msg_create(alloc->pool, PJ_STUN_DATA_INDICATION,
				    PJ_STUN_MAGIC, NULL, &alloc->data_ind);
	if (status != PJ_SUCCESS) {
	    pj_activesock_close(alloc->sock);
	    pj_pool_release(alloc->pool);
	    pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp);
	    goto send_pkt;
	}
	pj_stun_msg_add_sockaddr_attr(alloc->pool, alloc->data_ind, 
				      PJ_STUN_ATTR_XOR_PEER_ADDR, PJ_TRUE,
				      &alloc->alloc_addr,
				      pj_sockaddr_get_len(&alloc->alloc_addr));
	pj_stun_msg_add_binary_attr(alloc->pool, alloc->data_ind,
				    PJ_STUN_ATTR_DATA, (pj_uint8_t*)"", 1);

	/* Create response */
	resp = create_success_response(test_srv, alloc, req, pool, 600, &auth_key);
	if (resp == NULL) {
	    pj_activesock_close(alloc->sock);
	    pj_pool_release(alloc->pool);
	    pj_stun_msg_create_response(pool, req, PJ_STUN_SC_SERVER_ERROR, NULL, &resp);
	    goto send_pkt;
	}

	++test_srv->turn_alloc_cnt;

    } else {
	alloc = &test_srv->turn_alloc[i];

	if (req->hdr.type == PJ_STUN_ALLOCATE_REQUEST) {

	    test_srv->turn_stat.rx_allocate_cnt++;

	    /* Skip if we're not responding to Allocate request */
	    if (!test_srv->turn_respond_allocate)
		return PJ_TRUE;

	    resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);

	} else if (req->hdr.type == PJ_STUN_REFRESH_REQUEST) {
	    pj_stun_lifetime_attr *lf_attr;

	    test_srv->turn_stat.rx_refresh_cnt++;

	    /* Skip if we're not responding to Refresh request */
	    if (!test_srv->turn_respond_refresh)
		return PJ_TRUE;

	    lf_attr = (pj_stun_lifetime_attr*)
		      pj_stun_msg_find_attr(req, PJ_STUN_ATTR_LIFETIME, 0);
	    if (lf_attr && lf_attr->value != 0) {
		resp = create_success_response(test_srv, alloc, req, pool, 600, &auth_key);
		pj_array_erase(test_srv->turn_alloc, sizeof(test_srv->turn_alloc[0]),
			       test_srv->turn_alloc_cnt, i);
		--test_srv->turn_alloc_cnt;
	    } else
		resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);
	} else if (req->hdr.type == PJ_STUN_CREATE_PERM_REQUEST) {
	    for (i=0; i<req->attr_count; ++i) {
		if (req->attr[i]->type == PJ_STUN_ATTR_XOR_PEER_ADDR) {
		    pj_stun_xor_peer_addr_attr *pa = (pj_stun_xor_peer_addr_attr*)req->attr[i];
		    unsigned j;

		    for (j=0; j<alloc->perm_cnt; ++j) {
			if (pj_sockaddr_cmp(&alloc->perm[j], &pa->sockaddr)==0)
			    break;
		    }

		    if (j==alloc->perm_cnt && alloc->perm_cnt < MAX_TURN_PERM) {
			char peer_info[PJ_INET6_ADDRSTRLEN];
			pj_sockaddr_print(&pa->sockaddr, peer_info, sizeof(peer_info), 3);

			pj_sockaddr_cp(&alloc->perm[alloc->perm_cnt], &pa->sockaddr);
			++alloc->perm_cnt;

			PJ_LOG(5,("", "Permission %s added to client %s, perm_cnt=%d", 
				      peer_info, client_info, alloc->perm_cnt));
		    }

		}
	    }
	    resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);
	} else if (req->hdr.type == PJ_STUN_SEND_INDICATION) {
	    pj_stun_xor_peer_addr_attr *pa;
	    pj_stun_data_attr *da;

	    test_srv->turn_stat.rx_send_ind_cnt++;

	    pa = (pj_stun_xor_peer_addr_attr*)
		 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);
	    da = (pj_stun_data_attr*)
		 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_DATA, 0);
	    if (pa && da) {
		unsigned j;
		char peer_info[PJ_INET6_ADDRSTRLEN];
		pj_ssize_t sent;

		pj_sockaddr_print(&pa->sockaddr, peer_info, sizeof(peer_info), 3);

		for (j=0; j<alloc->perm_cnt; ++j) {
		    if (pj_sockaddr_cmp(&alloc->perm[j], &pa->sockaddr)==0)
			break;
		}

		if (j==alloc->perm_cnt) {
		    PJ_LOG(5,("", "SendIndication to %s is rejected (no permission)", 
			          peer_info, client_info, alloc->perm_cnt));
		} else {
		    PJ_LOG(5,(THIS_FILE, "Relaying %d bytes data from client %s to peer %s, "
					 "perm_cnt=%d", 
			      da->length, client_info, peer_info, alloc->perm_cnt));

		    sent = da->length;
		    pj_activesock_sendto(alloc->sock, &alloc->send_key,
					 da->data, &sent, 0,
					 &pa->sockaddr,
					 pj_sockaddr_get_len(&pa->sockaddr));
		}
	    } else {
		PJ_LOG(1,(THIS_FILE, "Invalid Send Indication from %s", client_info));
	    }
	} else if (req->hdr.type == PJ_STUN_CHANNEL_BIND_REQUEST) {
	    pj_stun_xor_peer_addr_attr *pa;
	    pj_stun_channel_number_attr *cna;
	    unsigned j, cn;

	    pa = (pj_stun_xor_peer_addr_attr*)
		 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_XOR_PEER_ADDR, 0);
	    cna = (pj_stun_channel_number_attr*)
		 pj_stun_msg_find_attr(req, PJ_STUN_ATTR_CHANNEL_NUMBER, 0);
	    cn = PJ_STUN_GET_CH_NB(cna->value);

	    resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);

	    for (j=0; j<alloc->perm_cnt; ++j) {
		if (pj_sockaddr_cmp(&alloc->perm[j], &pa->sockaddr)==0)
		    break;
	    }

	    if (i==alloc->perm_cnt) {
		if (alloc->perm_cnt==MAX_TURN_PERM) {
		    pj_stun_msg_create_response(pool, req, PJ_STUN_SC_INSUFFICIENT_CAPACITY, NULL, &resp);
		    goto send_pkt;
		}
		pj_sockaddr_cp(&alloc->perm[i], &pa->sockaddr);
		++alloc->perm_cnt;
	    }
	    alloc->chnum[i] = cn;

	    resp = create_success_response(test_srv, alloc, req, pool, 0, &auth_key);

	} else if (PJ_STUN_IS_REQUEST(req->hdr.type)) {
	    pj_stun_msg_create_response(pool, req, PJ_STUN_SC_BAD_REQUEST, NULL, &resp);
	}
    }


send_pkt:
    if (resp) {
	status = pj_stun_msg_encode(resp, (pj_uint8_t*)data, MAX_STUN_PKT, 
				    0, &auth_key, &size);
	if (status != PJ_SUCCESS)
	    goto on_return;

	len = size;
	status = pj_activesock_sendto(asock, &test_srv->send_key, data, &len,
				      0, src_addr, addr_len);
    }

on_return:
    pj_pool_release(pool);
    return PJ_TRUE;
}
コード例 #9
0
ファイル: stun_session.c プロジェクト: AmongOthers/PJSIP-iOS
static pj_status_t apply_msg_options(pj_stun_session *sess,
				     pj_pool_t *pool,
				     const pj_stun_req_cred_info *auth_info,
				     pj_stun_msg *msg)
{
    pj_status_t status = 0;
    pj_str_t realm, username, nonce, auth_key;

    /* If the agent is sending a request, it SHOULD add a SOFTWARE attribute
     * to the request. The server SHOULD include a SOFTWARE attribute in all 
     * responses.
     *
     * If magic value is not PJ_STUN_MAGIC, only apply the attribute for
     * responses.
     */
    if (sess->srv_name.slen && 
	pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_SOFTWARE, 0)==NULL &&
	(PJ_STUN_IS_RESPONSE(msg->hdr.type) ||
	 (PJ_STUN_IS_REQUEST(msg->hdr.type) && msg->hdr.magic==PJ_STUN_MAGIC))) 
    {
	pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SOFTWARE,
				    &sess->srv_name);
    }

    if (pj_stun_auth_valid_for_msg(msg) && auth_info) {
	realm = auth_info->realm;
	username = auth_info->username;
	nonce = auth_info->nonce;
	auth_key = auth_info->auth_key;
    } else {
	realm.slen = username.slen = nonce.slen = auth_key.slen = 0;
    }

    /* Create and add USERNAME attribute if needed */
    if (username.slen && PJ_STUN_IS_REQUEST(msg->hdr.type)) {
	status = pj_stun_msg_add_string_attr(pool, msg,
					     PJ_STUN_ATTR_USERNAME,
					     &username);
	PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
    }

    /* Add REALM only when long term credential is used */
    if (realm.slen &&  PJ_STUN_IS_REQUEST(msg->hdr.type)) {
	status = pj_stun_msg_add_string_attr(pool, msg,
					    PJ_STUN_ATTR_REALM,
					    &realm);
	PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
    }

    /* Add NONCE when desired */
    if (nonce.slen && 
	(PJ_STUN_IS_REQUEST(msg->hdr.type) ||
	 PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type))) 
    {
	status = pj_stun_msg_add_string_attr(pool, msg,
					    PJ_STUN_ATTR_NONCE,
					    &nonce);
    }

    /* Add MESSAGE-INTEGRITY attribute */
    if (username.slen && auth_key.slen) {
	status = pj_stun_msg_add_msgint_attr(pool, msg);
	PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
    }


    /* Add FINGERPRINT attribute if necessary */
    if (sess->use_fingerprint) {
	status = pj_stun_msg_add_uint_attr(pool, msg, 
					  PJ_STUN_ATTR_FINGERPRINT, 0);
	PJ_ASSERT_RETURN(status==PJ_SUCCESS, status);
    }

    return PJ_SUCCESS;
}