Commit f60b60f9 authored by Youness Alaoui's avatar Youness Alaoui

add the ice usage and the corresponding test

parent 4c5132fd
...@@ -21,7 +21,8 @@ libstun_la_SOURCES = stun.h constants.h \ ...@@ -21,7 +21,8 @@ libstun_la_SOURCES = stun.h constants.h \
stun3489bis.c stun3489bis.h \ stun3489bis.c stun3489bis.h \
stuncrc32.c stuncrc32.h \ stuncrc32.c stuncrc32.h \
stunhmac.c stunhmac.h \ stunhmac.c stunhmac.h \
utils.c utils.h utils.c utils.h \
stun-ice.c stun-ice.h
libstun_la_LIBADD = $(OPENSSL_LIBS) $(LIBRT) libstun_la_LIBADD = $(OPENSSL_LIBS) $(LIBRT)
/*
* This file is part of the Nice GLib ICE library.
*
* (C) 2007 Nokia Corporation. All rights reserved.
* Contact: Rémi Denis-Courmont
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Nice GLib ICE library.
*
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
* Corporation. All Rights Reserved.
*
* Contributors:
* Rémi Denis-Courmont, Nokia
*
* Alternatively, the contents of this file may be used under the terms of the
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
* case the provisions of LGPL are applicable instead of those above. If you
* wish to allow use of your version of this file only under the terms of the
* LGPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replace
* them with the notice and other provisions required by the LGPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the LGPL.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "tools/bind.h"
#include "stunagent.h"
#include <errno.h>
/** ICE connectivity checks **/
#include "stun-ice.h"
static int
stun_bind_error (StunAgent *agent, StunMessage *msg,
uint8_t *buf, size_t *plen, const StunMessage *req,
stun_error_t code, const uint8_t *key, size_t key_len)
{
size_t len = *plen;
int val;
*plen = 0;
stun_debug ("STUN Error Reply (buffer size: %u)...\n", (unsigned)len);
val = stun_agent_init_error (agent, msg, buf, len, req, code);
if (!val)
return val;
len = stun_agent_finish_message (agent, msg, key, key_len);
if (len == 0)
return 0;
*plen = len;
stun_debug (" Error response (%u) of %u bytes\n", (unsigned)code,
(unsigned)*plen);
return 1;
}
int
stun_conncheck_reply (StunAgent *agent, StunMessage *req,
const uint8_t *rbuf, size_t rlen,
StunMessage *msg, uint8_t *buf, size_t *plen,
const struct sockaddr *restrict src, socklen_t srclen,
const uint8_t *local_ufrag, const size_t ufrag_len,
const uint8_t *password, const size_t password_len,
bool *restrict control, uint64_t tie, uint32_t compat)
{
const char *username = NULL;
uint16_t username_len;
size_t len = *plen;
uint64_t q;
int val = 0, ret = 0;
stun_validater_data validater_data[] = {
{local_ufrag, ufrag_len, password, password_len},
{NULL, 0, NULL, 0}};
StunValidationStatus valid;
#define err( code ) \
stun_bind_error (agent, msg, buf, &len, req, code, password, password_len); \
*plen = len
*plen = 0;
stun_debug ("STUN Reply (buffer size = %u)...\n", (unsigned)len);
valid = stun_agent_validate (agent, req, rbuf, rlen,
stun_agent_default_validater, validater_data);
stun_debug ("validated : %d\n", valid);
if (valid == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE)
{
stun_debug (" Unknown mandatory attributes in message.\n");
len = stun_agent_build_unknown_attributes_error (agent, msg, buf, len, req);
if (len == 0)
goto failure;
*plen = len;
return EPROTO;
}
if (valid == STUN_VALIDATION_NOT_STUN ||
valid == STUN_VALIDATION_INCOMPLETE_STUN ||
valid == STUN_VALIDATION_BAD_REQUEST)
{
stun_debug (" Incorrectly multiplexed STUN message ignored.\n");
return EINVAL;
}
if (stun_message_get_class (req) != STUN_REQUEST)
{
stun_debug (" Unhandled non-request (class %u) message.\n",
stun_message_get_class (req));
return EINVAL;
}
if (stun_message_get_method (req) != STUN_BINDING)
{
stun_debug (" Bad request (method %u) message.\n",
stun_message_get_method (req));
err (STUN_ERROR_BAD_REQUEST);
return EPROTO;
}
if (valid == STUN_VALIDATION_UNAUTHORIZED) {
stun_debug (" Integrity check failed.\n");
err (STUN_ERROR_UNAUTHORIZED);
return EPERM;
}
if (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST) {
stun_debug (" Integrity check failed.\n");
err (STUN_ERROR_BAD_REQUEST);
return EPERM;
}
username = (const char *)stun_message_find (req,
STUN_ATTRIBUTE_USERNAME, &username_len);
/* Role conflict handling */
assert (control != NULL);
if (!stun_message_find64 (req, *control ? STUN_ATTRIBUTE_ICE_CONTROLLING
: STUN_ATTRIBUTE_ICE_CONTROLLED, &q))
{
stun_debug ("STUN Role Conflict detected:\n");
if (tie < q)
{
stun_debug (" switching role from \"controll%s\" to \"controll%s\"\n",
*control ? "ing" : "ed", *control ? "ed" : "ing");
*control = !*control;
ret = EACCES;
}
else
{
stun_debug (" staying \"controll%s\" (sending error)\n",
*control ? "ing" : "ed");
*plen = len;
err (STUN_ERROR_ROLE_CONFLICT);
return 0;
}
}
#ifndef NDEBUG
else
if (stun_message_find64 (req, *control ? STUN_ATTRIBUTE_ICE_CONTROLLED
: STUN_ATTRIBUTE_ICE_CONTROLLING, &q))
stun_debug ("STUN Role not specified by peer!\n");
#endif
stun_agent_init_response (agent, msg, buf, len, req);
if (!stun_has_cookie (msg)) {
val = stun_message_append_addr (msg, STUN_ATTRIBUTE_MAPPED_ADDRESS, src, srclen);
} else {
val = stun_message_append_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
src, srclen);
}
if (val)
{
stun_debug (" Mapped address problem: %s\n", strerror (val));
goto failure;
}
if (username) {
stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
username, username_len);
}
len = stun_agent_finish_message (agent, msg, password, password_len);
if (len == 0)
goto failure;
*plen = len;
stun_debug (" All done (response size: %u)\n", (unsigned)len);
return ret;
failure:
assert (*plen == 0);
stun_debug (" Fatal error formatting Response: %s\n", strerror (val));
return val;
}
#undef err
uint32_t stun_conncheck_priority (const StunMessage *msg)
{
uint32_t value;
if (stun_message_find32 (msg, STUN_ATTRIBUTE_PRIORITY, &value))
return 0;
return value;
}
bool stun_conncheck_use_candidate (const StunMessage *msg)
{
return !stun_message_find_flag (msg, STUN_ATTRIBUTE_USE_CANDIDATE);
}
/*
* This file is part of the Nice GLib ICE library.
*
* (C) 2007 Nokia Corporation. All rights reserved.
* Contact: Rémi Denis-Courmont
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Nice GLib ICE library.
*
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
* Corporation. All Rights Reserved.
*
* Contributors:
* Rémi Denis-Courmont, Nokia
*
* Alternatively, the contents of this file may be used under the terms of the
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
* case the provisions of LGPL are applicable instead of those above. If you
* wish to allow use of your version of this file only under the terms of the
* LGPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replace
* them with the notice and other provisions required by the LGPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the LGPL.
*/
#ifndef STUN_CONNCHECK_H
# define STUN_CONNCHECK_H 1
/**
* @file stun-ice.h
* @brief STUN/ICE connectivity checks
*/
# include "stun/tools/bind.h"
# ifdef __cplusplus
extern "C" {
# endif
/**
* Starts a connectivity check using STUN Binding discovery.
*
* @param context pointer to an opaque pointer that will be passed to
* stun_bind_resume() afterward
* @param fd socket to use for discovery, or -1 to create one
* @param srv STUN server socket address
* @param srvlen STUN server socket address length
* @param username nul-terminated username for authentication
* (need not be kept valid after return)
* @param password nul-terminated shared secret (ICE password)
* (need not be kept valid after return)
* @param cand_use whether to include a USE-CANDIDATE flag
* @param priority host-byte order PRIORITY value
* @param controlling whether we are in controlling (true) or
* controlled (false) state
* @param tie control tie breaker value (host-byte order)
*
* @return 0 on success, a standard error value otherwise.
*/
int stun_conncheck_start (stun_bind_t **restrict context, int fd,
const struct sockaddr *restrict srv, socklen_t srvlen,
const char *username, const char *password,
bool cand_use, bool controlling, uint32_t priority,
uint64_t tie, uint32_t compat);
/**
* Tries to parse a STUN connectivity check (Binding request) and format a
* response accordingly.
*
* @param buf [OUT] output buffer to write a Binding response to. May refer
* to the same buffer space as the request message.
* @param plen [IN/OUT] output buffer size on entry, response length on exit
* @param msg pointer to the first byte of the binding request
* @param src socket address the message was received from
* @param srclen byte length of the socket address
* @param username STUN username
* @param password HMAC secret password
* @param control [IN/OUT] whether we are controlling ICE or not
* @param tie tie breaker value for ICE role determination
*
* @return 0 if successful (@a rbuf contains a <b>non-error</b> response),
* EINVAL: malformatted request message or socket address,
* EAFNOSUPPORT: unsupported socket address family,
* EPROTO: unsupported request message type or parameter,
* ENOBUFS: insufficient response buffer space.
* EACCES: ICE role conflict occurred, please recheck the flag at @a control
*
* In case of error, the value at @a plen is set to the size of an error
* response, or 0 if no error response should be sent.
*/
int
stun_conncheck_reply (StunAgent *agent, StunMessage *req,
const uint8_t *rbuf, size_t rlen,
StunMessage *msg, uint8_t *buf, size_t *plen,
const struct sockaddr *restrict src, socklen_t srclen,
const uint8_t *local_ufrag, const size_t ufrag_len,
const uint8_t *password, const size_t password_len,
bool *restrict control, uint64_t tie, uint32_t compat);
/**
* Extracts the priority from a STUN message.
* @param msg valid STUN message.
* @return host byte order priority, or 0 if not specified.
*/
uint32_t stun_conncheck_priority (const StunMessage *msg);
/**
* Extracts the "use candidate" flag from a STUN message.
* @param msg valid STUN message.
* @return true if the flag is set, false if not.
*/
bool stun_conncheck_use_candidate (const StunMessage *msg);
# ifdef __cplusplus
}
# endif
#endif
...@@ -13,7 +13,8 @@ LDADD = ../libstun.la ...@@ -13,7 +13,8 @@ LDADD = ../libstun.la
check_PROGRAMS = \ check_PROGRAMS = \
test-parse \ test-parse \
test-format \ test-format \
test-bind test-bind \
test-conncheck
test_bind_SOURCES = test-bind.c \ test_bind_SOURCES = test-bind.c \
../tools/bind.c \ ../tools/bind.c \
......
...@@ -39,8 +39,8 @@ ...@@ -39,8 +39,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include "stun/usages/stun-ice.h" #include "stun/stunagent.h"
#include "stun/stun-msg.h" #include "stun/stun-ice.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
...@@ -56,14 +56,28 @@ ...@@ -56,14 +56,28 @@
int main (void) int main (void)
{ {
struct sockaddr_in ip4; struct sockaddr_in ip4;
stun_msg_t req, resp; uint8_t req_buf[STUN_MAX_MESSAGE_SIZE];
uint8_t resp_buf[STUN_MAX_MESSAGE_SIZE];
const uint64_t tie = 0x8000000000000000LL; const uint64_t tie = 0x8000000000000000LL;
ssize_t val; ssize_t val;
size_t len; size_t len;
size_t rlen;
static const char username[] = "L:R", ufrag[] = "L", pass[] = "secret"; static const char username[] = "L:R", ufrag[] = "L", pass[] = "secret";
int code; int code;
uint16_t alen; uint16_t alen;
bool control = false; bool control = false;
StunAgent agent;
StunMessage req;
StunMessage resp;
stun_validater_data validater_data[] = {
{ufrag, strlen (ufrag), pass, strlen (pass)},
{username, strlen (username), pass, strlen (pass)},
{NULL, 0, NULL, 0}};
stun_agent_init (&agent, STUN_ALL_KNOWN_ATTRIBUTES,
STUN_COMPATIBILITY_3489BIS,
STUN_AGENT_USAGE_USE_FINGERPRINT |
STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);
memset (&ip4, 0, sizeof (ip4)); memset (&ip4, 0, sizeof (ip4));
ip4.sin_family = AF_INET; ip4.sin_family = AF_INET;
...@@ -74,174 +88,222 @@ int main (void) ...@@ -74,174 +88,222 @@ int main (void)
ip4.sin_addr.s_addr = htonl (0x7f000001); ip4.sin_addr.s_addr = htonl (0x7f000001);
/* Incorrect message class */ /* Incorrect message class */
stun_init_request (req, STUN_BINDING); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
stun_init_response (req, sizeof (req), req, 0); assert (stun_agent_init_response (&agent, &req, req_buf, sizeof (req_buf), &req));
len = sizeof (req);
val = stun_finish (req, &len, 0);
assert (val == 0);
len = sizeof (resp); rlen = stun_agent_finish_message (&agent, &req, NULL, 0);
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, assert (rlen > 0);
sizeof (ip4), ufrag, pass, &control, tie, 0);
len = sizeof (resp_buf);
val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
&resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), pass, strlen (pass), &control, tie, 0);
assert (val == EINVAL); assert (val == EINVAL);
assert (len == 0); assert (len == 0);
/* Incorrect message method */ /* Incorrect message method */
stun_init_request (req, 0x666); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), 0x666));
len = sizeof (req); val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, username);
val = stun_finish_short (req, &len, username, pass, NULL, 0);
assert (val == 0); assert (val == 0);
rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
assert (rlen > 0);
len = sizeof (resp); len = sizeof (resp_buf);
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
sizeof (ip4), ufrag, pass, &control, tie, 0); &resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), pass, strlen (pass), &control, tie, 0);
assert (val == EPROTO); assert (val == EPROTO);
assert (len > 0); assert (len > 0);
/* Unknown attribute */ /* Unknown attribute */
stun_init_request (req, STUN_BINDING); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
val = stun_append_string (req, sizeof (req), 0x666, val = stun_message_append_string (&req, 0x666, "The evil unknown attribute!");
"The evil unknown attribute!");
assert (val == 0); assert (val == 0);
len = sizeof (req); val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, username);
val = stun_finish (req, &len, 0);
assert (val == 0); assert (val == 0);
rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
assert (rlen > 0);
len = sizeof (resp); len = sizeof (resp_buf);
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
sizeof (ip4), username, pass, &control, tie, 0); &resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), username, strlen (username), pass, strlen (pass), &control, tie, 0);
assert (val == EPROTO); assert (val == EPROTO);
assert (len > 0); assert (len > 0);
/* Unauthenticated message */ /* Unauthenticated message */
stun_init_request (req, STUN_BINDING); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
len = sizeof (req); rlen = stun_agent_finish_message (&agent, &req, NULL, 0);
val = stun_finish (req, &len, 0); assert (rlen > 0);
assert (val == 0);
len = sizeof (resp); len = sizeof (resp_buf);
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
sizeof (ip4), ufrag, pass, &control, tie, 0); &resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), pass, strlen (pass), &control, tie, 0);
assert (val == EPERM); assert (val == EPERM);
assert (len > 0); assert (len > 0);
assert (stun_match_messages (resp, req, NULL, 0, &code) assert (stun_agent_validate (&agent, &resp, resp_buf, len,
&& (code == STUN_BAD_REQUEST)); stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
stun_message_find_error (&resp, &code);
assert (code == STUN_ERROR_BAD_REQUEST);
/* No username */ /* No username */
stun_init_request (req, STUN_BINDING); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
len = sizeof (req); rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
val = stun_finish_short (req, &len, NULL, pass, NULL, 0); assert (rlen > 0);
assert (val == 0);
len = sizeof (resp); len = sizeof (resp_buf);
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
sizeof (ip4), ufrag, pass, &control, tie, 0); &resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), pass, strlen (pass), &control, tie, 0);
assert (val == EPERM); assert (val == EPERM);
assert (len > 0); assert (len > 0);
assert (stun_match_messages (resp, req, NULL, 0, &code) assert (stun_agent_validate (&agent, &resp, resp_buf, len,
&& (code == STUN_BAD_REQUEST)); stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
assert (stun_conncheck_priority (req) == 0); stun_message_find_error (&resp, &code);
assert (stun_conncheck_use_candidate (req) == false); assert (code == STUN_ERROR_BAD_REQUEST);
assert (stun_conncheck_priority (&req) == 0);
assert (stun_conncheck_use_candidate (&req) == false);
/* Good message */ /* Good message */
stun_init_request (req, STUN_BINDING); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
val = stun_append32 (req, sizeof (req), STUN_PRIORITY, 0x12345678); val = stun_message_append32 (&req, STUN_ATTRIBUTE_PRIORITY, 0x12345678);
assert (val == 0); assert (val == 0);
val = stun_append_flag (req, sizeof (req), STUN_USE_CANDIDATE); val = stun_message_append_flag (&req, STUN_ATTRIBUTE_USE_CANDIDATE);
assert (val == 0); assert (val == 0);
len = sizeof (req); val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, ufrag);
val = stun_finish_short (req, &len, username, pass, NULL, 0);
assert (val == 0); assert (val == 0);
rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
assert (rlen > 0);
len = sizeof (resp); len = sizeof (resp_buf);
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
sizeof (ip4), ufrag, pass, &control, tie, 0); &resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), pass, strlen (pass), &control, tie, 0);
assert (val == 0); assert (val == 0);
assert (len > 0); assert (len > 0);
assert (stun_match_messages (resp, req, (uint8_t *)pass, assert (stun_agent_validate (&agent, &resp, resp_buf, len,
strlen (pass), &code) stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
&& (code == -1)); assert (stun_message_get_class (&resp) == STUN_RESPONSE);
assert (stun_conncheck_priority (req) == 0x12345678); assert (stun_conncheck_priority (&req) == 0x12345678);
assert (stun_conncheck_use_candidate (req) == true); assert (stun_conncheck_use_candidate (&req) == true);
/* Bad username */ /* Bad username */
len = sizeof (resp); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, ufrag);
sizeof (ip4), "bad", pass, &control, tie, 0); assert (val == 0);
rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
assert (rlen > 0);
len = sizeof (resp_buf);
val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
&resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), "bad", strlen ("bad"), pass, strlen (pass), &control, tie, 0);
assert (val == EPERM); assert (val == EPERM);
assert (len > 0); assert (len > 0);
assert (stun_match_messages (resp, req, NULL, 0, &code) assert (stun_agent_validate (&agent, &resp, resp_buf, len,
&& (code == STUN_UNAUTHORIZED)); stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
assert (stun_message_get_class (&resp) == STUN_ERROR);
stun_message_find_error (&resp, &code);
assert (code == STUN_ERROR_UNAUTHORIZED);
/* Bad integrity (bad password) */ /* Bad integrity (bad password) */
len = sizeof (resp); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, ufrag);
sizeof (ip4), ufrag, "bad", &control, tie, 0); assert (val == 0);
rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
assert (rlen > 0);
len = sizeof (resp_buf);
val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
&resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), "bad", strlen ("bad"), &control, tie, 0);
assert (val == EPERM); assert (val == EPERM);
assert (len > 0); assert (len > 0);
assert (stun_match_messages (resp, req, NULL, 0, &code) assert (stun_agent_validate (&agent, &resp, resp_buf, len,
&& (code == STUN_UNAUTHORIZED)); stun_agent_default_validater, validater_data) == STUN_VALIDATION_UNAUTHORIZED);
assert (stun_message_get_class (&resp) == STUN_ERROR);
stun_message_find_error (&resp, &code);
assert (code == STUN_ERROR_UNAUTHORIZED);
/* Invalid socket address */ /* Invalid socket address */
assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, ufrag);
assert (val == 0);
rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
assert (rlen > 0);
ip4.sin_family = AF_UNSPEC; ip4.sin_family = AF_UNSPEC;
len = sizeof (resp); len = sizeof (resp_buf);
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
sizeof (ip4), ufrag, pass, &control, tie, 0); &resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), pass, strlen (pass), &control, tie, 0);
assert (val == EAFNOSUPPORT); assert (val == EAFNOSUPPORT);
assert (len == 0);
ip4.sin_family = AF_INET; ip4.sin_family = AF_INET;
/* Bad CRC32 */ /* Bad CRC32 */
stun_init_request (req, STUN_BINDING); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
len = sizeof (req); val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, ufrag);
val = stun_finish_short (req, &len, ufrag, pass, NULL, 0);
assert (val == 0); assert (val == 0);
((uint8_t *)stun_find (req, STUN_FINGERPRINT, &alen))[0] ^= 1; rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
assert (rlen > 0);
((uint8_t *)stun_message_find (&req, STUN_ATTRIBUTE_FINGERPRINT, &alen))[0] ^= 1;
len = sizeof (resp); len = sizeof (resp_buf);
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
sizeof (ip4), ufrag, pass, &control, tie, 0); &resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), pass, strlen (pass), &control, tie, 0);
assert (val == EINVAL); assert (val == EINVAL);
assert (len == 0); assert (len == 0);
/* Lost role conflict */ /* Lost role conflict */
stun_init_request (req, STUN_BINDING); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
val = stun_append64 (req, sizeof (req), STUN_ICE_CONTROLLING, tie + 1); val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLING, tie + 1);
assert (val == 0); assert (val == 0);
len = sizeof (req); val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, ufrag);
val = stun_finish_short (req, &len, username, pass, NULL, 0);
assert (val == 0); assert (val == 0);
rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
assert (rlen > 0);
len = sizeof (resp);
len = sizeof (resp_buf);
control = true; control = true;
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
sizeof (ip4), ufrag, pass, &control, tie, 0); &resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), pass, strlen (pass), &control, tie, 0);
assert (val == EACCES); assert (val == EACCES);
assert (len > 0); assert (len > 0);
assert (control == false); assert (control == false);
assert (stun_match_messages (resp, req, (uint8_t *)pass, assert (stun_agent_validate (&agent, &resp, resp_buf, len,
strlen (pass), &code) stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
&& (code == -1)); assert (stun_message_get_class (&resp) == STUN_RESPONSE);
/* Won role conflict */ /* Won role conflict */
stun_init_request (req, STUN_BINDING); assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
val = stun_append64 (req, sizeof (req), STUN_ICE_CONTROLLED, tie - 1); val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLED, tie - 1);
assert (val == 0); assert (val == 0);
len = sizeof (req); val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, ufrag);
val = stun_finish_short (req, &len, username, pass, NULL, 0);
assert (val == 0); assert (val == 0);
rlen = stun_agent_finish_message (&agent, &req, pass, strlen (pass));
assert (rlen > 0);
len = sizeof (resp); len = sizeof (resp_buf);
control = false; control = false;
val = stun_conncheck_reply (resp, &len, req, (struct sockaddr *)&ip4, val = stun_conncheck_reply (&agent, &req, req_buf, rlen,
sizeof (ip4), ufrag, pass, &control, tie, 0); &resp, resp_buf, &len, (struct sockaddr *)&ip4,
sizeof (ip4), ufrag, strlen (ufrag), pass, strlen (pass), &control, tie, 0);
assert (val == 0); assert (val == 0);
assert (len > 0); assert (len > 0);
assert (control == false); assert (control == false);
assert (stun_match_messages (resp, req, (uint8_t *)pass, assert (stun_agent_validate (&agent, &resp, resp_buf, len,
strlen (pass), &code) stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
&& (code == STUN_ROLE_CONFLICT)); assert (stun_message_get_class (&resp) == STUN_ERROR);
stun_message_find_error (&resp, &code);
assert (code == STUN_ERROR_ROLE_CONFLICT);
return 0; return 0;
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment