Beispiel #1
0
static void
dynamic_check (StunAgent *agent, StunMessage *msg, size_t len)
{
  StunMessage msg2;

  if (stun_agent_validate (agent, &msg2, msg->buffer, len, dynamic_check_validater, NULL) != STUN_VALIDATION_SUCCESS)
    fatal ("Could not validate message");

  printf ("Built message of %u bytes\n", (unsigned)len);
}
Beispiel #2
0
int main (void)
{
  union {
    struct sockaddr sa;
    struct sockaddr_storage storage;
    struct sockaddr_in ip4;
  } addr;
  uint8_t req_buf[STUN_MAX_MESSAGE_SIZE];
  uint8_t resp_buf[STUN_MAX_MESSAGE_SIZE];
  const const uint64_t tie = 0x8000000000000000LL;
  StunMessageReturn val;
  StunUsageIceReturn val2;
  size_t len;
  size_t rlen;
  static char username[] = "L:R";
  static uint8_t ufrag[] = "L", pass[] = "secret";
  size_t ufrag_len = strlen ((char*) ufrag);
  size_t pass_len = strlen ((char*) pass);
  int code;
  bool control = false;
  StunAgent agent;
  StunMessage req;
  StunMessage resp;
  StunDefaultValidaterData validater_data[] = {
    {ufrag, ufrag_len, pass, pass_len},
    {(uint8_t *) username, strlen (username), pass, pass_len},
    {NULL, 0, NULL, 0}};
  StunValidationStatus valid;

  stun_agent_init (&agent, STUN_ALL_KNOWN_ATTRIBUTES,
      STUN_COMPATIBILITY_RFC5389,
      STUN_AGENT_USAGE_USE_FINGERPRINT |
      STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);

  memset (&addr, 0, sizeof (addr));
  addr.ip4.sin_family = AF_INET;
#ifdef HAVE_SA_LEN
  addr.ip4.sin_len = sizeof (addr);
#endif
  addr.ip4.sin_port = htons (12345);
  addr.ip4.sin_addr.s_addr = htonl (0x7f000001);

  /* Incorrect message class */
  assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
  assert (stun_agent_init_response (&agent, &req, req_buf, sizeof (req_buf), &req));

  rlen = stun_agent_finish_message (&agent, &req, NULL, 0);
  assert (rlen > 0);

  len = sizeof (resp_buf);
  val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
      &resp, resp_buf, &len, &addr.storage,
      sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
  assert (val2 == STUN_USAGE_ICE_RETURN_INVALID_REQUEST);
  assert (len == 0);

  /* Incorrect message method */
  assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), 0x666));
  val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, username);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
  assert (rlen > 0);

  len = sizeof (resp_buf);
  val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
      &resp, resp_buf, &len, &addr.storage,
      sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
  assert (val2 == STUN_USAGE_ICE_RETURN_INVALID_METHOD);
  assert (len > 0);

  /* Unknown attribute */
  assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
  val = stun_message_append_string (&req, 0x666, "The evil unknown attribute!");
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME, username);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
  assert (rlen > 0);

  valid = stun_agent_validate (&agent, &req, req_buf, rlen,
      stun_agent_default_validater, validater_data);

  assert (valid == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE);

  /* Unauthenticated message */
  assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
  rlen = stun_agent_finish_message (&agent, &req, NULL, 0);
  assert (rlen > 0);

  valid = stun_agent_validate (&agent, &req, req_buf, rlen,
      stun_agent_default_validater, validater_data);

  assert (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST);

  /* No username */
  assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
  rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
  assert (rlen > 0);

  valid = stun_agent_validate (&agent, &req, req_buf, rlen,
      stun_agent_default_validater, validater_data);

  assert (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST);
  assert (stun_usage_ice_conncheck_priority (&req) == 0);
  assert (stun_usage_ice_conncheck_use_candidate (&req) == false);

  /* Good message */
  assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
  val = stun_message_append32 (&req, STUN_ATTRIBUTE_PRIORITY, 0x12345678);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  val = stun_message_append_flag (&req, STUN_ATTRIBUTE_USE_CANDIDATE);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
      (char*) ufrag);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
  assert (rlen > 0);

  len = sizeof (resp_buf);
  val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
      &resp, resp_buf, &len, &addr.storage,
      sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
  assert (val2 == STUN_USAGE_ICE_RETURN_SUCCESS);
  assert (len > 0);
  assert (stun_agent_validate (&agent, &resp, resp_buf, len,
          stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
  assert (stun_message_get_class (&resp) == STUN_RESPONSE);
  assert (stun_usage_ice_conncheck_priority (&req) == 0x12345678);
  assert (stun_usage_ice_conncheck_use_candidate (&req) == true);

  /* 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,
      (char *) ufrag);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
  assert (rlen > 0);

  addr.ip4.sin_family = AF_UNSPEC;
  len = sizeof (resp_buf);
  val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
      &resp, resp_buf, &len, &addr.storage,
      sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
  assert (val2 == STUN_USAGE_ICE_RETURN_INVALID_ADDRESS);
  assert (len == 0);

  addr.ip4.sin_family = AF_INET;

  /* Lost role conflict */
  assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
  val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLING, tie + 1);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
     (char *) ufrag);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
  assert (rlen > 0);


  len = sizeof (resp_buf);
  control = true;
  val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
      &resp, resp_buf, &len, &addr.storage,
      sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
  assert (val2 == STUN_USAGE_ICE_RETURN_ROLE_CONFLICT);
  assert (len > 0);
  assert (control == false);
  assert (stun_agent_validate (&agent, &resp, resp_buf, len,
          stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
  assert (stun_message_get_class (&resp) == STUN_RESPONSE);

  /* Won role conflict */
  assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
  val = stun_message_append64 (&req, STUN_ATTRIBUTE_ICE_CONTROLLED, tie - 1);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
      (char *) ufrag);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
  assert (rlen > 0);

  len = sizeof (resp_buf);
  control = false;
  val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
      &resp, resp_buf, &len, &addr.storage,
      sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
  assert (val2 == STUN_USAGE_ICE_RETURN_SUCCESS);
  assert (len > 0);
  assert (control == false);
  assert (stun_agent_validate (&agent, &resp, resp_buf, len,
          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_ROLE_CONFLICT);


  return 0;
}
Beispiel #3
0
static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
{
  union {
    struct sockaddr_storage storage;
    struct sockaddr addr;
  } addr;
  socklen_t addr_len;
  uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  size_t buf_len = 0;
  size_t len = 0;
  StunMessage request;
  StunMessage response;
  StunValidationStatus validation;
  StunAgent *agent = NULL;
  gint ret;

  addr_len = sizeof (struct sockaddr_in);

recv_packet:
  len = recvfrom (sock, buf, sizeof(buf), 0,
      &addr.addr, &addr_len);

  if (drop_stun_packets) {
    g_debug ("Dropping STUN packet as requested");
    return -1;
  }

  if (len == (size_t)-1) {
    return -1;
  }

  validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0);

  if (validation == STUN_VALIDATION_SUCCESS) {
    agent = newagent;
  } else {
    validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0);
    agent = oldagent;
  }

  /* Unknown attributes */
  if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE) {
    buf_len = stun_agent_build_unknown_attributes_error (agent, &response, buf,
        sizeof (buf), &request);
    goto send_buf;
  }

  /* Mal-formatted packets */
  if (validation != STUN_VALIDATION_SUCCESS ||
      stun_message_get_class (&request) != STUN_REQUEST) {
    goto recv_packet;
  }

  switch (stun_message_get_method (&request)) {
    case STUN_BINDING:
      stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
      if (stun_message_has_cookie (&request))
        stun_message_append_xor_addr (&response,
            STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
            &addr.storage, addr_len);
      else
         stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
             &addr.addr, addr_len);
      break;

    case STUN_SHARED_SECRET:
    case STUN_ALLOCATE:
    case STUN_SET_ACTIVE_DST:
    case STUN_CONNECT:
    case STUN_OLD_SET_ACTIVE_DST:
    case STUN_IND_DATA:
    case STUN_IND_CONNECT_STATUS:
    case STUN_CHANNELBIND:
    default:
      if (!stun_agent_init_error (agent, &response, buf, sizeof (buf),
              &request, STUN_ERROR_BAD_REQUEST)) {
        g_debug ("STUN error message not initialized properly");
        g_assert_not_reached();
      }
  }

  buf_len = stun_agent_finish_message (agent, &response, NULL, 0);

send_buf:
  g_cancellable_cancel (global_cancellable);
  g_debug ("Ready to send a STUN response");
  g_assert (g_mutex_trylock (stun_mutex_ptr));
  got_stun_packet = TRUE;
  while (send_stun) {
    g_debug ("Waiting for signal. State is %d", global_lagent_state);
    g_cond_wait (stun_signal_ptr, stun_mutex_ptr);
  }
  g_mutex_unlock (stun_mutex_ptr);
  len = sendto (sock, buf, buf_len, 0,
      &addr.addr, addr_len);
  g_debug ("STUN response sent");
  drop_stun_packets = TRUE;
  ret = (len < buf_len) ? -1 : 0;
  return ret;
}
/** Malformed responses test */
static void bad_responses (void)
{
  struct sockaddr_storage addr;
  socklen_t addrlen = sizeof (addr);
  ssize_t val, len;
  uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  uint8_t req[STUN_MAX_MESSAGE_SIZE];
  size_t req_len;
  StunAgent agent;
  StunMessage msg;
  StunMessage req_msg;
  int servfd, fd;

  uint16_t known_attributes[] = {
    STUN_ATTRIBUTE_MAPPED_ADDRESS,
    STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
    STUN_ATTRIBUTE_PRIORITY,
    STUN_ATTRIBUTE_USERNAME,
    STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
    STUN_ATTRIBUTE_ERROR_CODE, 0};

  stun_agent_init (&agent, known_attributes,
      STUN_COMPATIBILITY_RFC5389, 0);

  /* Allocate a local UDP port */
  servfd = listen_dgram ();
  assert (servfd != -1);

  val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);

  fd = socket (addr.ss_family, SOCK_DGRAM, 0);
  assert (fd != -1);

  req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
  assert (req_len > 0);

  val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
      (struct sockaddr *)&addr, addrlen);
  assert (val >= 0);

  /* Send to/receive from our client instance only */
  val = getsockname (fd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);

  /* Send request instead of response */
  val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);
  len = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
  assert (len >= 20);

  assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
      == STUN_VALIDATION_SUCCESS);

  val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
      (struct sockaddr *) &addr, &addrlen);
  assert (val == STUN_USAGE_BIND_RETURN_INVALID);

  /* Send response with wrong request type */
  buf[0] |= 0x03;
  buf[0] ^= 0x02;

  /* Send error response without ERROR-CODE */
  buf[1] |= 0x10;
  val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
      (struct sockaddr *) &addr, &addrlen);
  assert (val == STUN_USAGE_BIND_RETURN_INVALID);

  close (fd);
  close (servfd);
}
/** Various responses test */
static void responses (void)
{
  struct sockaddr_storage addr;
  socklen_t addrlen = sizeof (addr);
  ssize_t val;
  size_t len;
  int servfd, fd;
  uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  uint8_t req[STUN_MAX_MESSAGE_SIZE];
  size_t req_len;
  StunAgent agent;
  StunMessage msg;
  StunMessage req_msg;

  uint16_t known_attributes[] = {
    STUN_ATTRIBUTE_MAPPED_ADDRESS,
    STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
    STUN_ATTRIBUTE_PRIORITY,
    STUN_ATTRIBUTE_USERNAME,
    STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
    STUN_ATTRIBUTE_ERROR_CODE, 0};

  stun_agent_init (&agent, known_attributes,
      STUN_COMPATIBILITY_RFC5389, 0);

  /* Allocate a local UDP port for server */
  servfd = listen_dgram ();
  assert (servfd != -1);

  val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);

  /* Allocate a client socket and connect to server */
  fd = socket (addr.ss_family, SOCK_DGRAM, 0);
  assert (fd != -1);

  /* Send error response */
  req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
  assert (req_len > 0);

  val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);

  val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
      (struct sockaddr *)&addr, addrlen);
  assert (val >= 0);

  val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
  assert (val >= 0);

  assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
      == STUN_VALIDATION_SUCCESS);

  stun_agent_init_error (&agent, &msg, buf, sizeof (buf),
      &msg, STUN_ERROR_SERVER_ERROR);
  len = stun_agent_finish_message (&agent, &msg, NULL, 0);
  assert (len > 0);

  val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);

  val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
      (struct sockaddr *) &addr, &addrlen);
  assert (val == STUN_USAGE_BIND_RETURN_ERROR);

  /* Send response with a no mapped address at all */
  req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
  assert (req_len > 0);

  val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);

  val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
      (struct sockaddr *)&addr, addrlen);
  assert (val >= 0);

  val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
  assert (val >= 0);

  assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
      == STUN_VALIDATION_SUCCESS);

  stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
  len = stun_agent_finish_message (&agent, &msg, NULL, 0);
  assert (len > 0);

  assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
      == STUN_VALIDATION_SUCCESS);

  val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);

  val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
      (struct sockaddr *) &addr, &addrlen);
  assert (val == STUN_USAGE_BIND_RETURN_ERROR);

  /* Send old-style response */
  req_len = stun_usage_bind_create (&agent, &req_msg, req, sizeof(req));
  assert (req_len > 0);

  val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);

  val = sendto (fd, req, req_len, MSG_DONTWAIT | MSG_NOSIGNAL,
      (struct sockaddr *)&addr, addrlen);
  assert (val >= 0);

  val = recvfrom (servfd, buf, 1000, MSG_DONTWAIT, NULL, 0);
  assert (val >= 0);

  assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
      == STUN_VALIDATION_SUCCESS);

  stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
  assert (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
          (struct sockaddr *) &addr, addrlen) == STUN_MESSAGE_RETURN_SUCCESS);
  len = stun_agent_finish_message (&agent, &msg, NULL, 0);
  assert (len > 0);

  assert (stun_agent_validate (&agent, &msg, buf, len, NULL, NULL)
      == STUN_VALIDATION_SUCCESS);

  val = getsockname (servfd, (struct sockaddr *)&addr, &addrlen);
  assert (val == 0);

  val = stun_usage_bind_process (&msg, (struct sockaddr *) &addr, &addrlen,
      (struct sockaddr *) &addr, &addrlen);
  assert (val == STUN_USAGE_BIND_RETURN_SUCCESS);

  /* End */
  close (servfd);

  val = close (fd);
  assert (val == 0);
}
Beispiel #6
0
static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
{
  struct sockaddr_storage addr;
  uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  char ctlbuf[CMSG_SPACE (sizeof (struct in6_pktinfo))];
  struct iovec iov = { buf, sizeof (buf) };
  StunMessage request;
  StunMessage response;
  StunValidationStatus validation;
  StunAgent *agent = NULL;

  struct msghdr mh =
  {
    .msg_name = (struct sockaddr *)&addr,
    .msg_namelen = sizeof (addr),
    .msg_iov = &iov,
    .msg_iovlen = 1,
    .msg_control = ctlbuf,
    .msg_controllen = sizeof (ctlbuf)
  };

  size_t len = recv_safe (sock, &mh);
  if (len == (size_t)-1)
    return -1;

  validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0);

  if (validation == STUN_VALIDATION_SUCCESS) {
    agent = newagent;
  }
  else {
    validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0);
    agent = oldagent;
  }

  /* Unknown attributes */
  if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE)
  {
    stun_agent_build_unknown_attributes_error (agent, &response, buf,
        sizeof (buf), &request);
    goto send_buf;
  }

  /* Mal-formatted packets */
  if (validation != STUN_VALIDATION_SUCCESS ||
      stun_message_get_class (&request) != STUN_REQUEST) {
    return -1;
  }

  switch (stun_message_get_method (&request))
  {
    case STUN_BINDING:
      stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
      if (stun_message_has_cookie (&request))
        stun_message_append_xor_addr (&response,
                              STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
                              mh.msg_name, mh.msg_namelen);
      else
         stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
                          mh.msg_name, mh.msg_namelen);
      break;

    default:
      stun_agent_init_error (agent, &response, buf, sizeof (buf),
          &request, STUN_ERROR_BAD_REQUEST);
  }

  iov.iov_len = stun_agent_finish_message (agent, &response, NULL, 0);
send_buf:

  len = send_safe (sock, &mh);
  return (len < iov.iov_len) ? -1 : 0;
}


static int run (int family, int protocol, unsigned port)
{
  StunAgent oldagent;
  StunAgent newagent;
  int sock = listen_socket (family, SOCK_DGRAM, protocol, port);
  if (sock == -1)
    return -1;

  stun_agent_init (&oldagent, known_attributes,
      STUN_COMPATIBILITY_RFC3489, 0);
  stun_agent_init (&newagent, known_attributes,
      STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);

  for (;;)
    dgram_process (sock, &oldagent, &newagent);
}
Beispiel #7
0
static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
{
  union {
    struct sockaddr_storage storage;
    struct sockaddr addr;
  } addr;
  socklen_t addr_len;
  uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  size_t buf_len = 0;
  size_t len = 0;
  StunMessage request;
  StunMessage response;
  StunValidationStatus validation;
  StunAgent *agent = NULL;

  addr_len = sizeof (struct sockaddr_in);
  len = recvfrom (sock, buf, sizeof(buf), 0, &addr.addr, &addr_len);
  if (len == (size_t)-1)
    return -1;

  validation = stun_agent_validate (newagent, &request, buf, len, NULL, 0);

  if (validation == STUN_VALIDATION_SUCCESS) {
    agent = newagent;
  }
  else {
    validation = stun_agent_validate (oldagent, &request, buf, len, NULL, 0);
    agent = oldagent;
  }

  /* Unknown attributes */
  if (validation == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE)
  {
    buf_len = stun_agent_build_unknown_attributes_error (agent, &response, buf,
        sizeof (buf), &request);
    goto send_buf;
  }

  /* Mal-formatted packets */
  if (validation != STUN_VALIDATION_SUCCESS ||
      stun_message_get_class (&request) != STUN_REQUEST) {
    return -1;
  }

  switch (stun_message_get_method (&request))
  {
    case STUN_BINDING:
      stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
      if (stun_message_has_cookie (&request))
        stun_message_append_xor_addr (&response,
            STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr.addr, addr_len);
      else
         stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
             &addr.addr, addr_len);
      break;

    case STUN_SHARED_SECRET:
    case STUN_ALLOCATE:
    case STUN_SEND:
    case STUN_CONNECT:
    case STUN_IND_SEND:
    case STUN_IND_DATA:
    case STUN_CREATEPERMISSION:
    case STUN_CHANNELBIND:
    default:
      if (!stun_agent_init_error (agent, &response, buf, sizeof (buf),
              &request, STUN_ERROR_BAD_REQUEST))
        return -1;
  }

  buf_len = stun_agent_finish_message (agent, &response, NULL, 0);
send_buf:
  len = sendto (sock, buf, buf_len, 0, &addr.addr, addr_len);
  return (len < buf_len) ? -1 : 0;
}
Beispiel #8
0
/** Various responses test */
static void test_turn (char *username, char *password, char *hostname, int port)
{
  struct sockaddr_storage addr;
  socklen_t addrlen = sizeof (addr);
  struct sockaddr_storage alternate_addr;
  socklen_t alternate_addrlen = sizeof (alternate_addr);
  struct sockaddr_storage relay_addr;
  socklen_t relay_addrlen = sizeof (relay_addr);
  ssize_t val;
  size_t len;
  int fd;
  uint8_t buf[STUN_MAX_MESSAGE_SIZE];
  uint8_t req[STUN_MAX_MESSAGE_SIZE];
  uint8_t refresh[STUN_MAX_MESSAGE_SIZE];
  size_t req_len;
  StunAgent agent;
  StunMessage msg;
  StunMessage req_msg;
  StunMessage refresh_msg;
  uint32_t bandwidth, lifetime;
  struct addrinfo hints, *res;
  int ret = -1;

  memset (&hints, 0, sizeof (hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_DGRAM;
  hints.ai_flags = 0;

  ret = getaddrinfo (hostname, port, &hints, &res);
  assert (ret == 0);

  stun_agent_init (&agent, STUN_ALL_KNOWN_ATTRIBUTES,
      STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS);

  /* Allocate a client socket and connect to server */
  fd = socket (AF_INET, SOCK_DGRAM, 0);
  assert (fd != -1);

  val = connect (fd,res->ai_addr, res->ai_addrlen);
#ifdef G_OS_WIN32
  assert (val == 0 || (WSAGetLastError () == WSAEINPROGRESS));
#else
  assert (val == 0 || (errno == EINPROGRESS));
#endif

  freeaddrinfo (res);


  /* Send old-style response */
  req_len = stun_usage_turn_create (&agent, &req_msg, req, sizeof(req),
      NULL,
      STUN_USAGE_TURN_REQUEST_PORT_NORMAL,
      -1, -1,
      username, strlen (username), password, strlen(password),
      STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
  assert (req_len > 0);

  val = send (fd, req, req_len, MSG_NOSIGNAL);
  assert (val >= 0);

  val = recv (fd, buf, 1000, 0);
  assert (val >= 0);

  assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
      == STUN_VALIDATION_SUCCESS);

  val = stun_usage_turn_process (&msg,
      (struct sockaddr *)&relay_addr, &relay_addrlen,
      (struct sockaddr *)&addr, &addrlen,
      (struct sockaddr *)&alternate_addr, &alternate_addrlen,
      &bandwidth, &lifetime,
      STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
  assert (val == STUN_USAGE_TURN_RETURN_ERROR);

  req_len = stun_usage_turn_create (&agent, &req_msg, req, sizeof(req),
      &msg,
      STUN_USAGE_TURN_REQUEST_PORT_NORMAL,
      -1, -1,
      username, strlen (username), password, strlen(password),
      STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
  assert (req_len > 0);

  val = send (fd, req, req_len, MSG_NOSIGNAL);
  assert (val >= 0);

  val = recv (fd, buf, 1000, 0);
  assert (val >= 0);

  assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
      == STUN_VALIDATION_SUCCESS);

  val = stun_usage_turn_process (&msg,
      (struct sockaddr *)&relay_addr, &relay_addrlen,
      (struct sockaddr *)&addr, &addrlen,
      (struct sockaddr *)&alternate_addr, &alternate_addrlen,
      &bandwidth, &lifetime,
      STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
  assert (val == STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS);

  printaddr ("Relay address found : ", (struct sockaddr *)&relay_addr, relay_addrlen);
  printaddr ("Mapped address found : ",(struct sockaddr *) &addr, addrlen);


  req_len = stun_usage_turn_create_refresh (&agent, &refresh_msg, refresh,
      sizeof(refresh),  &req_msg, 0, username, strlen (username),
      password, strlen(password),STUN_USAGE_TURN_COMPATIBILITY_DRAFT9);
  assert (req_len > 0);

  val = send (fd, refresh, req_len, MSG_NOSIGNAL);
  assert (val >= 0);

  val = recv (fd, buf, 1000, 0);
  assert (val >= 0);

  assert (stun_agent_validate (&agent, &msg, buf, val, NULL, NULL)
      == STUN_VALIDATION_SUCCESS);

  val = close (fd);
  assert (val == 0);
}
Beispiel #9
0
int handle_stun(udp_conn* c, uint8_t *packet, size_t len) {

  StunAgent agent;
  StunValidationStatus status;
  StunAgentUsageFlags flags;
  StunMessage request;
  StunMessage response;
  int ret;
  size_t output_size;
  uint8_t output[1024];

  flags = STUN_AGENT_USAGE_IGNORE_CREDENTIALS; //  | STUN_AGENT_USAGE_USE_FINGERPRINT;  

  static const uint16_t attr[] = { 
    STUN_ATTRIBUTE_MAPPED_ADDRESS,
    STUN_ATTRIBUTE_RESPONSE_ADDRESS,
    STUN_ATTRIBUTE_CHANGE_REQUEST,
    STUN_ATTRIBUTE_SOURCE_ADDRESS,
    STUN_ATTRIBUTE_CHANGED_ADDRESS,
    STUN_ATTRIBUTE_USERNAME,
    STUN_ATTRIBUTE_PASSWORD,
    STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
    STUN_ATTRIBUTE_ERROR_CODE,
    STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES,
    STUN_ATTRIBUTE_REFLECTED_FROM,
    STUN_ATTRIBUTE_CHANNEL_NUMBER,
    STUN_ATTRIBUTE_LIFETIME,
    STUN_ATTRIBUTE_MS_ALTERNATE_SERVER,
    STUN_ATTRIBUTE_MAGIC_COOKIE,
    STUN_ATTRIBUTE_BANDWIDTH,
    STUN_ATTRIBUTE_DESTINATION_ADDRESS,
    STUN_ATTRIBUTE_REMOTE_ADDRESS,
    STUN_ATTRIBUTE_PEER_ADDRESS,
    STUN_ATTRIBUTE_XOR_PEER_ADDRESS,
    STUN_ATTRIBUTE_DATA,
    STUN_ATTRIBUTE_REALM,
    STUN_ATTRIBUTE_NONCE,
    STUN_ATTRIBUTE_RELAY_ADDRESS,
    STUN_ATTRIBUTE_RELAYED_ADDRESS,
    STUN_ATTRIBUTE_XOR_RELAYED_ADDRESS,
    STUN_ATTRIBUTE_REQUESTED_ADDRESS_TYPE,
    STUN_ATTRIBUTE_REQUESTED_PORT_PROPS,
    STUN_ATTRIBUTE_REQUESTED_PROPS,
    STUN_ATTRIBUTE_EVEN_PORT,
    STUN_ATTRIBUTE_REQUESTED_TRANSPORT,
    STUN_ATTRIBUTE_DONT_FRAGMENT,
    STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
    STUN_ATTRIBUTE_TIMER_VAL,
    STUN_ATTRIBUTE_REQUESTED_IP,
    STUN_ATTRIBUTE_RESERVATION_TOKEN,
    STUN_ATTRIBUTE_CONNECT_STAT,
    STUN_ATTRIBUTE_PRIORITY,
    STUN_ATTRIBUTE_USE_CANDIDATE,
    STUN_ATTRIBUTE_OPTIONS,
    STUN_ATTRIBUTE_MS_VERSION,
    STUN_ATTRIBUTE_SOFTWARE,
    STUN_ATTRIBUTE_ALTERNATE_SERVER,
    STUN_ATTRIBUTE_FINGERPRINT,
    STUN_ATTRIBUTE_ICE_CONTROLLED,
    STUN_ATTRIBUTE_ICE_CONTROLLING,
    STUN_ATTRIBUTE_MS_SEQUENCE_NUMBER,
    STUN_ATTRIBUTE_CANDIDATE_IDENTIFIER
  };

  /* initialize our agent to be compatible with RFC5389 (= with TLS support) */
  output_size = 0;
  memset(output, 0, sizeof(output));
  stun_agent_init(&agent, attr, STUN_COMPATIBILITY_RFC5389, flags);

  /* validate the request */
  status = stun_agent_validate(&agent, &request, packet, len, NULL, NULL);
  print_stun_validation_status(status);

  /* check the class */
  StunClass request_class = stun_message_get_class(&request);
  print_stun_class(request_class);
  if(request_class == STUN_ERROR) {
    printf("Error: request stun class failed.\n");
    exit(0);
  }

  /* what stun method? */
  StunMethod request_method = stun_message_get_method(&request);
  print_stun_method(request_method);

  /* initialize the response */
  ret = stun_agent_init_response(&agent, &response, output, 1024, &request);
  printf("Stun agent_init_response ret: %d\n", ret);

  /* add xor-mapped-address */
  uint32_t magic_cookie = 0;
  uint8_t* cookie_ptr = NULL;
  StunTransactionId transid;
  socklen_t sock_len = 0;
  char client_ip[16] = { 0 } ;
  StunMessageReturn stun_ret = STUN_MESSAGE_RETURN_INVALID;

  stun_message_id(&response, transid);
  magic_cookie = *((uint32_t*)transid);
  sock_len = sizeof(c->client);
  cookie_ptr = (uint8_t*) &magic_cookie;
  inet_ntop(AF_INET, &c->client.sin_addr.s_addr, client_ip, sizeof(client_ip));

  stun_ret = stun_message_append_xor_addr(&response, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, (const struct sockaddr*)&c->client, sock_len);
  print_stun_message_return(stun_ret);

  printf("Received data from: %s\n", client_ip);
  printf("Magic cookie: %02X %02X %02X %02X\n", cookie_ptr[0], cookie_ptr[1], cookie_ptr[2], cookie_ptr[3]);
  
  // username
  // --------
  const char* username = NULL;
  uint16_t username_len = 0;
  username = (const char*)stun_message_find(&request, STUN_ATTRIBUTE_USERNAME, &username_len);
  printf("Username: %s, len: %d\n", username, (int)username_len);

#if 0
  if(username) {
    StunMessageReturn username_res = stun_message_append_bytes(&response, STUN_ATTRIBUTE_USERNAME, username, username_len);
    print_stun_message_return(username_res);

  }
  uint32_t fingerprint = 0;
  if(stun_message_find32(&request, STUN_ATTRIBUTE_FINGERPRINT, &fingerprint) == STUN_MESSAGE_RETURN_SUCCESS) {
    printf("Got fingerprint: %d\n", fingerprint);
    if(stun_message_append32(&response, STUN_ATTRIBUTE_FINGERPRINT, fingerprint) != STUN_MESSAGE_RETURN_SUCCESS) {
      printf("Error while adding the fingerprint.\n");
    }
  }
#endif

  // password
  const char* password = ucon_ptr->stun_pw; // "94ccca06d14fb48c135bdaff30560c4d";
  uint16_t password_len = strlen(password) + 1;
  output_size = stun_agent_finish_message(&agent, &response, (const uint8_t*) password, password_len);

  // answer to the connection
  krx_udp_send(c, output, output_size);

  print_buffer(output, output_size);
  return 0;
}
Beispiel #10
0
/* Tests for generic message validation routines */
static void test_message (void)
{
  static const uint8_t extra_garbage[] =
      {0x15, 0x55, 0x00, 0x00,
       0x21, 0x12, 0xA4, 0x42, // cookie
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x76, 0x54, 0x32, 0x10,
       0xaa, 0xbb, 0xcc, 0xdd}; //extra garbage
  static const uint8_t simple_resp[] =
      {0x15, 0x55, 0x00, 0x00,
       0x21, 0x12, 0xA4, 0x42, // cookie
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x76, 0x54, 0x32, 0x10};
  static const uint8_t old_ind[] =
      {0x14, 0x55, 0x00, 0x00,
       0xfe, 0xdc, 0xba, 0x98, // NO cookie
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x76, 0x54, 0x32, 0x10};
  static const uint8_t fpr_resp[] =
      {0x15, 0x55, 0x00, 0x10,
       0x21, 0x12, 0xA4, 0x42, // cookie
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x76, 0x54, 0x32, 0x10,
       0x00, 0x06, 0x00, 0x04, // dummy USERNAME header
       0x41, 0x42, 0x43, 0x44,
       0x80, 0x28, 0x00, 0x04, // FINGERPRINT header
       0xdc, 0x8d, 0xa7, 0x74}; // CRC32;
  static const uint8_t bad1[32] =
      {0x15, 0x55, 0x00, 0x08,
       0x21, 0x12, 0xA4, 0x42, // cookie
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x76, 0x54, 0x32, 0x10,
       0x00, 0x06, 0x00, 0x05, // too big attribute for message
       0x11, 0x22, 0x33, 0x44,
       0x55, 0x66, 0x77, 0x88};
  static const uint8_t bad2[24] =
      {0x15, 0x55, 0x00, 0x05, // invalid message length
       0x21, 0x12, 0xA4, 0x42,
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x76, 0x54, 0x32, 0x10,
       0x00, 0x06, 0x00, 0x01};
  static const uint8_t bad3[27] =
      {0x15, 0x55, 0x00, 0x08,
       0x21, 0x12, 0xA4, 0x42,
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x76, 0x54, 0x32, 0x10,
       0x00, 0x06, 0x00, 0x03,
       0x11, 0x22, 0x33}; // missing padding
  static const uint8_t bad_crc[] =
      {0x15, 0x55, 0x00, 0x08,
       0x21, 0x12, 0xA4, 0x42,
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x76, 0x54, 0x32, 0x10,
       0x80, 0x28, 0x00, 0x04, // FINGERPRINT header
       0x04, 0x91, 0xcd, 0x78}; // CRC32
  static uint8_t bad_crc_offset[] =
      {0x15, 0x55, 0x00, 0x10,
       0x21, 0x12, 0xA4, 0x42,
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x20, 0x67, 0xc4, 0x09,
       0x80, 0x28, 0x00, 0x04, // FINGERPRINT header
       0x00, 0x00, 0x00, 0x00,
       0x00, 0x06, 0x00, 0x04,
       0x41, 0x42, 0x43, 0x44};

  static unsigned char req[] =
      {0x00, 0x01, 0x00, 0x00,
       0x8b, 0x45, 0x9b, 0xc3,
       0xe7, 0x7a, 0x05, 0xb3,
       0xe4, 0xfe, 0x01, 0xf0,
       0xaf, 0x83, 0xe1, 0x9e};

  static uint8_t binding_error_resp[] =
      {0x01, 0x11, 0x00, 0x84,
       0x8b, 0x45, 0x9b, 0xc3,
       0xe7, 0x7a, 0x05, 0xb3,
       0xe4, 0xfe, 0x01, 0xf0,
       0xaf, 0x83, 0xe1, 0x9e,

       0x00, 0x06, 0x00, 0x48, // USERNAME
       0x92, 0x6b, 0x2b, 0x3e,
       0x6a, 0xa5, 0x43, 0x58,
       0xa8, 0x51, 0x25, 0xa6,
       0xf7, 0x9c, 0x0a, 0xe7,
       0xd8, 0x86, 0xf7, 0x76,
       0xf9, 0xcd, 0x8a, 0x2e,
       0x45, 0xd7, 0xcb, 0xbb,
       0xae, 0xe5, 0x03, 0xc3,
       0x3a, 0x32, 0x3a, 0xa9,
       0x9e, 0xb7, 0x7b, 0x32,
       0xe3, 0xf3, 0xa6, 0xc0,
       0xe8, 0x54, 0x4b, 0xef,
       0x52, 0xd2, 0xe2, 0xc0,
       0x43, 0xc2, 0x4c, 0xbc,
       0xaf, 0xd9, 0xf2, 0xfa,
       0x48, 0x8b, 0x8c, 0xe6,
       0x62, 0x14, 0x64, 0x3a,
       0x32, 0x00, 0x00, 0x00,

       0x00, 0x09, 0x00, 0x1c, // ERROR-CODE
       0x00, 0x00, 0x04, 0x1f,
       0x49, 0x6e, 0x74, 0x65,
       0x67, 0x72, 0x69, 0x74,
       0x79, 0x20, 0x43, 0x68,
       0x65, 0x63, 0x6b, 0x20,
       0x46, 0x61, 0x69, 0x6c,
       0x75, 0x72, 0x65, 0x2e,

       0x00, 0x08, 0x00, 0x14, // MESSAGE-INTEGRITY
       0xf7, 0x46, 0x81, 0xc4,
       0x6f, 0x4c, 0x21, 0x5c,
       0xf6, 0x8e, 0xc0, 0x81,
       0x0e, 0x20, 0x3f, 0xb1,
       0xb1, 0xad, 0xa4, 0x8a};

  StunAgent agent;
  StunAgent agent2;
  StunMessage msg;
  uint16_t known_attributes[] = {STUN_ATTRIBUTE_USERNAME,
                                 STUN_ATTRIBUTE_ERROR_CODE,
                                 STUN_ATTRIBUTE_MESSAGE_INTEGRITY};

  uint8_t username_v[] = {0x92, 0x6b, 0x2b, 0x3e, 0x6a, 0xa5, 0x43, 0x58,
                          0xa8, 0x51, 0x25, 0xa6, 0xf7, 0x9c, 0x0a, 0xe7,
                          0xd8, 0x86, 0xf7, 0x76, 0xf9, 0xcd, 0x8a, 0x2e,
                          0x45, 0xd7, 0xcb, 0xbb, 0xae, 0xe5, 0x03, 0xc3,
                          0x3a, 0x32, 0x3a, 0xa9, 0x9e, 0xb7, 0x7b, 0x32,
                          0xe3, 0xf3, 0xa6, 0xc0, 0xe8, 0x54, 0x4b, 0xef,
                          0x52, 0xd2, 0xe2, 0xc0, 0x43, 0xc2, 0x4c, 0xbc,
                          0xaf, 0xd9, 0xf2, 0xfa, 0x48, 0x8b, 0x8c, 0xe6,
                          0x62, 0x14, 0x64, 0x3a, 0x32, 0x00, 0x00, 0x00};
  uint8_t password_v[]  = {0x77, 0xd9, 0x7a, 0xe9, 0xcf, 0xe0, 0x3e, 0xa2,
                           0x28, 0xa0, 0x5d, 0xec, 0xcf, 0x36, 0xe8, 0x49};

  StunDefaultValidaterData v = {username_v, 72, password_v, 16};

  stun_agent_init (&agent, known_attributes,
      STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_USE_FINGERPRINT);
  stun_agent_init (&agent2, known_attributes,
      STUN_COMPATIBILITY_RFC3489, STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);


  stun_agent_validate (&agent2, &msg, req, sizeof(req),  NULL, NULL);
  stun_agent_finish_message (&agent2, &msg, NULL, 0);

  if (stun_agent_validate (&agent2, &msg, binding_error_resp,
          sizeof(binding_error_resp),
          stun_agent_default_validater, &v) != STUN_VALIDATION_SUCCESS)
    fatal ("Binding Error Response failed");


  if (stun_message_validate_buffer_length (NULL, 0, TRUE) !=
      STUN_MESSAGE_BUFFER_INVALID)
    fatal ("0 bytes test failed");
  if (stun_message_validate_buffer_length ((uint8_t *)"\xf0", 1, TRUE) >= 0)
    fatal ("1 byte test failed");
  if (stun_message_validate_buffer_length (bad1, sizeof (bad1), TRUE) >= 0)
    fatal ("Badness 1 test failed");
  if (stun_message_validate_buffer_length (bad2, sizeof (bad2), TRUE) >= 0)
    fatal ("Badness 2 test failed");
  if (stun_message_validate_buffer_length (bad3, sizeof (bad3), TRUE) != 0)
    fatal ("Badness 3 test failed");
  validate (simple_resp, 20);
  validate (old_ind, 20);
  validate (fpr_resp, 36);

  if (stun_agent_validate (&agent, &msg, extra_garbage, sizeof(extra_garbage),
          NULL, NULL) != STUN_VALIDATION_NOT_STUN)
    fatal ("Extra garbage test failed");
  if (stun_agent_validate (&agent, &msg, simple_resp, sizeof(simple_resp),
          NULL, NULL) != STUN_VALIDATION_BAD_REQUEST)
    fatal ("Missing CRC test failed");
  if (stun_agent_validate (&agent, &msg, old_ind, sizeof(old_ind),
          NULL, NULL) != STUN_VALIDATION_BAD_REQUEST)
    fatal ("Missing cookie test failed");
  if (stun_agent_validate (&agent, &msg, bad_crc, sizeof(bad_crc),
          NULL, NULL) != STUN_VALIDATION_BAD_REQUEST)
    fatal ("Bad CRC test failed");
  if (stun_agent_validate (&agent, &msg, bad_crc_offset, sizeof(bad_crc_offset),
          NULL, NULL) != STUN_VALIDATION_BAD_REQUEST)
    fatal ("Bad CRC offset test failed");
  if (stun_agent_validate (&agent, &msg, fpr_resp, sizeof(fpr_resp),
          NULL, NULL) != STUN_VALIDATION_UNMATCHED_RESPONSE)
    fatal ("Good CRC test failed");

  if (stun_message_get_class (&msg) != 3)
    fatal ("Class test failed");
  if (stun_message_get_method (&msg) != 0x525)
    fatal ("Method test failed");
}
Beispiel #11
0
static void test_vectors (void)
{
  /* Request message */
  static unsigned char req[] =
      {0x00, 0x01, 0x00, 0x44,
       0x21, 0x12, 0xa4, 0x42,
       0xb7, 0xe7, 0xa7, 0x01,
       0xbc, 0x34, 0xd6, 0x86,
       0xfa, 0x87, 0xdf, 0xae,

       0x00, 0x24, 0x00, 0x04, // PRIORITY
       0x6e, 0x00, 0x01, 0xff,

       0x80, 0x29, 0x00, 0x08, // ICE_CONTROLLED
       0x93, 0x2f, 0xf9, 0xb1,
       0x51, 0x26, 0x3b, 0x36,

       0x00, 0x06, 0x00, 0x09, // USERNAME
       0x65, 0x76, 0x74, 0x6a,
       0x3a, 0x68, 0x36, 0x76,
       0x59, 0x20, 0x20, 0x20,

       0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY
       0x62, 0x4e, 0xeb, 0xdc,
       0x3c, 0xc9, 0x2d, 0xd8,
       0x4b, 0x74, 0xbf, 0x85,
       0xd1, 0xc0, 0xf5, 0xde,
       0x36, 0x87, 0xbd, 0x33,

       0x80, 0x28, 0x00, 0x04, // FINGERPRINT
       0xad, 0x8a, 0x85, 0xff};

  static const unsigned char req2[] =
      {0x00, 0x01, 0x00, 0x44,
       0x21, 0x12, 0xa4, 0x42,
       0xb7, 0xe7, 0xa7, 0x01,
       0xbc, 0x34, 0xd6, 0x86,
       0xfa, 0x87, 0xdf, 0xae,

       0x00, 0x24, 0x00, 0x04, // PRIORITY
       0x6e, 0x00, 0x01, 0xff,

       0x80, 0x29, 0x00, 0x08, // ICE_CONTROLLED
       0x93, 0x2f, 0xf9, 0xb1,
       0x51, 0x26, 0x3b, 0x36,

       0x00, 0x06, 0x00, 0x09, // USERNAME
       0x65, 0x76, 0x74, 0x6a,
       0x3a, 0x68, 0x36, 0x76,
       0x59, 0x20, 0x20, 0x20,

       0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY
       0x62, 0x4e, 0xeb, 0xdc,
       0x3c, 0xc9, 0x2d, 0xd8,
       0x4b, 0x74, 0xbf, 0x85,
       0xd1, 0xc0, 0xf5, 0xde,
       0x36, 0x87, 0xbd, 0x33,

       0x80, 0x28, 0x00, 0x04, // FINGERPRINT
       0xad, 0x8a, 0x85, 0xff};

  /* Response message */
  static const unsigned char respv4[] =
      {0x01, 0x01, 0x00, 0x4c,
       0x21, 0x12, 0xa4, 0x42,
       0xb7, 0xe7, 0xa7, 0x01,
       0xbc, 0x34, 0xd6, 0x86,
       0xfa, 0x87, 0xdf, 0xae,

       0x80, 0x22, 0x00, 0x0b, // SERVER
       0x74, 0x65, 0x73, 0x74,
       0x20, 0x76, 0x65, 0x63,
       0x74, 0x6f, 0x72, 0x20,

       0x00, 0x20, 0x00, 0x08, // XOR_MAPPED_ADDRESS
       0x00, 0x01, 0xa1, 0x47,
       0xe1, 0x12, 0xa6, 0x43,

       0x00, 0x06, 0x00, 0x09, // USERNAME
       0x65, 0x76, 0x74, 0x6a,
       0x3a, 0x68, 0x36, 0x76,
       0x59, 0x20, 0x20, 0x20,

       0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY
       0x7d, 0xb7, 0xfc, 0x52,
       0x70, 0xc6, 0xdb, 0x1f,
       0xc3, 0x26, 0x34, 0xbb,
       0x4c, 0x64, 0x6e, 0xe7,
       0x1d, 0xb3, 0x78, 0x4a,

       0x80, 0x28, 0x00, 0x04, // FINGERPRINT
       0xf0, 0x60, 0x66, 0xa9};
  static const unsigned char respv6[] =
      {0x01, 0x01, 0x00, 0x58,
       0x21, 0x12, 0xa4, 0x42,
       0xb7, 0xe7, 0xa7, 0x01,
       0xbc, 0x34, 0xd6, 0x86,
       0xfa, 0x87, 0xdf, 0xae,

       0x80, 0x22, 0x00, 0x0b, // SERVER
       0x74, 0x65, 0x73, 0x74,
       0x20, 0x76, 0x65, 0x63,
       0x74, 0x6f, 0x72, 0x20,

       0x00, 0x20, 0x00, 0x14, // XOR_MAPPED_ADDRESS
       0x00, 0x02, 0xa1, 0x47,
       0x01, 0x13, 0xa9, 0xfa,
       0xa5, 0xd3, 0xf1, 0x79,
       0xbc, 0x25, 0xf4, 0xb5,
       0xbe, 0xd2, 0xb9, 0xd9,

       0x00, 0x06, 0x00, 0x09, // USERNAME
       0x65, 0x76, 0x74, 0x6a,
       0x3a, 0x68, 0x36, 0x76,
       0x59, 0x20, 0x20, 0x20,

       0x00, 0x08, 0x00, 0x14, // MESSAGE_INTEGRITY
       0x21, 0xcb, 0xbd, 0x25,
       0x1a, 0x8c, 0x4c, 0x38,
       0x8c, 0xc5, 0xcd, 0xb3,
       0x27, 0x6a, 0xf5, 0x61,
       0xb2, 0x21, 0xc8, 0x2b,

       0x80, 0x28, 0x00, 0x04, // FINGERPRINT
       0xec, 0x27, 0xae, 0xb7};
  struct sockaddr_in ip4;
  struct sockaddr_in6 ip6;
  socklen_t addrlen;

  StunAgent agent;
  StunMessage msg;
  StunMessage msg2;
  uint16_t known_attributes[] = {
    STUN_ATTRIBUTE_MESSAGE_INTEGRITY,
    STUN_ATTRIBUTE_USERNAME,
    STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
    STUN_ATTRIBUTE_PRIORITY, 0};

  stun_agent_init (&agent, known_attributes,
      STUN_COMPATIBILITY_RFC5389,
      STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS |
      STUN_AGENT_USAGE_USE_FINGERPRINT);

  memset (&ip4, 0, sizeof (ip4));
  memset (&ip6, 0, sizeof (ip6));

  puts ("Checking test vectors...");

  if (stun_agent_validate (&agent, &msg2, req2, sizeof(req2),
          test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS)
    fatal ("Request test vector authentication failed");

  if (stun_agent_validate (&agent, &msg, req, sizeof(req),
          test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS)
    fatal ("Request test vector authentication failed");

  /* Remove the message-integrity and fingerprint attributes */
  req[3] = 0x24;

  if (stun_message_length (&msg) != sizeof(req) - 32)
    fatal ("vector test: removing attributes failed");

  stun_agent_finish_message (&agent, &msg, vector_password, strlen (vector_password));

  if (stun_message_length (&msg) != stun_message_length (&msg2) ||
      memcmp (req, req2, sizeof(req)) != 0)
    fatal ("vector test : req and req2 are different");

  if (stun_agent_validate (&agent, &msg, respv4, sizeof(respv4),
          test_vector_validater, (void *) 0) != STUN_VALIDATION_SUCCESS)
    fatal ("Response ipv4 test vector authentication failed");

  if (stun_agent_validate (&agent, &msg, respv4, sizeof(respv4),
          test_vector_validater, (void *) 0) != STUN_VALIDATION_UNMATCHED_RESPONSE)
    fatal ("Response ipv4 test vector authentication failed");

  addrlen = sizeof (ip4);
  if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
          (struct sockaddr *)&ip4, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
    fatal ("Response test vector IPv4 extraction failed");
  if (ip4.sin_family != AF_INET)
    fatal ("Response test vector IPv4 family failed");
  if (ntohl (ip4.sin_addr.s_addr) != 0xC0000201)
    fatal ("Response test vector IPv4 address failed");
  if (ntohs (ip4.sin_port) != 32853)
    fatal ("Response test vector IPv6 port failed");

  if (stun_agent_validate (&agent, &msg, req, sizeof(req),
          test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS)
    fatal ("Request test vector second authentication failed");

  /* Remove the fingerprint attributes */
  msg.key = NULL;
  msg.key_len = 0;
  req[3] = 0x3C;

  if (stun_message_length (&msg) != sizeof(req) - 8)
    fatal ("vector test: removing attributes failed");

  stun_agent_finish_message (&agent, &msg, NULL, 0);

  if (stun_message_length (&msg) != stun_message_length (&msg2) ||
      memcmp (req, req2, sizeof(req)) != 0)
    fatal ("vector test : req and req2 are different");

  if (stun_agent_validate (&agent, &msg, respv6, sizeof(respv6),
          test_vector_validater, (void *) 1) != STUN_VALIDATION_SUCCESS)
    fatal ("Response ipv6 test vector authentication failed");

  addrlen = sizeof (ip6);
  if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
          (struct sockaddr *)&ip6, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
    fatal ("Response test vector IPv6 extraction failed");
  if (ip6.sin6_family != AF_INET6)
    fatal ("Response test vector IPv6 family failed");
  if (memcmp (ip6.sin6_addr.s6_addr, "\x20\x01\x0d\xb8\x12\x34\x56\x78"
              "\x00\x11\x22\x33\x44\x55\x66\x77", 16) != 0)
    fatal ("Response test vector IPv6 address failed");
  if (ntohs (ip6.sin6_port) != 32853)
    fatal ("Response test vector IPv6 port failed");


  puts ("Done.");
}
Beispiel #12
0
/* Tests for message attribute parsing */
static void test_attribute (void)
{
  static const uint8_t acme[] =
      {0x04, 0x55, 0x00, 0x6C, // <-- update message length if needed!!
       0x21, 0x12, 0xA4, 0x42, // cookie
       0x76, 0x54, 0x32, 0x10,
       0xfe, 0xdc, 0xba, 0x98,
       0x76, 0x54, 0x32, 0x10,

       /* FF01: empty */
       0xff, 0x01, 0x00, 0x00,

       /* FF02: address of unknown family, 32-bits */
       0xff, 0x02, 0x00, 0x04,
       0x41, 0x42, 0x43, 0x44,

       /* FF03: too short IPv6 address */
       0xff, 0x03, 0x00, 0x06,
       0x00, 0x02, 0x12, 0x34,
       0x20, 0x01, 0x0d, 0xb8,

       /* FF04: valid IPv4 address, 64-bits */
       0xff, 0x04, 0x00, 0x08,
       0x00, 0x01, 0x12, 0x34,
       0xc0, 0x00, 0x02, 0x01,

       /* FF05: too long IPv4 address */
       0xff, 0x05, 0x00, 0x0A,
       0x00, 0x01, 0x12, 0x34,
       0xc0, 0x00, 0x02, 0x01,
       0x66, 0x60, 0x00, 0x00,

       /* FF06: valid xor'd IPv6 address, 160-bits */
       0xff, 0x06, 0x00, 0x14,
       0x00, 0x02, 0x12, 0x34,
       0x01, 0x13, 0xa9, 0xfa,
       0xa8, 0xf9, 0x8c, 0xff,
       0x20, 0x26, 0x74, 0x48,
       0x8c, 0x9a, 0xec, 0xfd,

       /* dummy USERNAME header */
       0x00, 0x06, 0x00, 0x04,
       0x41, 0x42, 0x43, 0x44,

       /* MESSAGE-INTEGRITY attribute */
       0x00, 0x08, 0x00, 0x14,
       0x0b, 0xc4, 0xb2, 0x0c,
       0x94, 0x58, 0xbb, 0x25,
       0xa3, 0x22, 0x1a, 0xc8,
       0xe1, 0x87, 0x32, 0x36,
       0x3a, 0xfc, 0xe2, 0xc3};

  union
  {
    struct sockaddr sa;
    struct sockaddr_in6 s6;
  } addr;
  socklen_t addrlen;
  uint32_t dword;
  uint64_t qword;
  char str[STUN_MAX_STR];

  StunAgent agent;
  StunMessage msg;
  uint16_t known_attributes[] = {STUN_ATTRIBUTE_MESSAGE_INTEGRITY, STUN_ATTRIBUTE_USERNAME, 0};

  printf ("Attribute test message length: %lu\n", sizeof (acme));

  stun_agent_init (&agent, known_attributes,
      STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS);

  if (stun_agent_validate (&agent, &msg, acme, sizeof(acme),
          NULL, NULL) != STUN_VALIDATION_UNAUTHORIZED)
    fatal ("Unauthorized validation failed");

  if (stun_agent_validate (&agent, &msg, acme, sizeof(acme),
          test_attribute_validater, "bad__guy") != STUN_VALIDATION_UNAUTHORIZED)
    fatal ("invalid password validation failed");

  if (stun_agent_validate (&agent, &msg, acme, sizeof(acme),
          test_attribute_validater, "good_guy") != STUN_VALIDATION_SUCCESS)
    fatal ("good password validation failed");

  if (stun_message_has_attribute (&msg, 0xff00))
    fatal ("Absent attribute test failed");
  if (!stun_message_has_attribute (&msg, 0xff01))
    fatal ("Present attribute test failed");

  if (stun_message_find_flag (&msg, 0xff00) != STUN_MESSAGE_RETURN_NOT_FOUND)
    fatal ("Absent flag test failed");
  if (stun_message_find_flag (&msg, 0xff01) != STUN_MESSAGE_RETURN_SUCCESS)
    fatal ("Flag test failed");
  if (stun_message_find_flag (&msg, 0xff02) != STUN_MESSAGE_RETURN_INVALID)
    fatal ("Too big flag test failed");

  if (stun_message_find32 (&msg, 0xff00, &dword) !=
      STUN_MESSAGE_RETURN_NOT_FOUND)
    fatal ("Absent dword test failed");
  if (stun_message_find32 (&msg, 0xff01, &dword) != STUN_MESSAGE_RETURN_INVALID)
    fatal ("Bad dword test failed");
  if (stun_message_find32 (&msg, 0xff02, &dword) != STUN_MESSAGE_RETURN_SUCCESS)
    fatal ("Double-word test failed");

  if (stun_message_find64 (&msg, 0xff00, &qword) !=
      STUN_MESSAGE_RETURN_NOT_FOUND)
    fatal ("Absent qword test failed");
  if (stun_message_find64 (&msg, 0xff01, &qword) != STUN_MESSAGE_RETURN_INVALID)
    fatal ("Bad qword test failed");
  if (stun_message_find64 (&msg, 0xff04, &qword) != STUN_MESSAGE_RETURN_SUCCESS)
    fatal ("Quad-word test failed");

  if (stun_message_find_string (&msg, 0xff00, str, STUN_MAX_CP) !=
      STUN_MESSAGE_RETURN_NOT_FOUND)
    fatal ("Absent string test failed");
  if ((stun_message_find_string (&msg, 0xff02, str, STUN_MAX_CP) !=
          STUN_MESSAGE_RETURN_SUCCESS)
   || strcmp (str, "ABCD"))
    fatal ("String test failed");

  addrlen = sizeof (addr);
  if (stun_message_find_addr (&msg, 0xff01, &addr.sa, &addrlen) !=
      STUN_MESSAGE_RETURN_INVALID)
    fatal ("Too short addres test failed");
  addrlen = sizeof (addr);
  if (stun_message_find_addr (&msg, 0xff02, &addr.sa, &addrlen) !=
      STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS)
    fatal ("Unknown address family test failed");
  addrlen = sizeof (addr);
  if (stun_message_find_addr (&msg, 0xff03, &addr.sa, &addrlen) !=
      STUN_MESSAGE_RETURN_INVALID)
    fatal ("Too short IPv6 address test failed");
  addrlen = sizeof (addr);
  if (stun_message_find_addr (&msg, 0xff04, &addr.sa, &addrlen) !=
      STUN_MESSAGE_RETURN_SUCCESS)
    fatal ("IPv4 address test failed");
  addrlen = sizeof (addr);
  if (stun_message_find_addr (&msg, 0xff05, &addr.sa, &addrlen) !=
      STUN_MESSAGE_RETURN_INVALID)
    fatal ("Too big IPv4 address test failed");
  addrlen = sizeof (addr);
  if (stun_message_find_xor_addr (&msg, 0xff06, &addr.sa, &addrlen) !=
      STUN_MESSAGE_RETURN_SUCCESS ||
      memcmp (&addr.s6.sin6_addr, "\x20\x01\x0d\xb8""\xde\xad\xbe\xef"
                                  "\xde\xfa\xce\xd0""\xfa\xce\xde\xed", 16))
    fatal ("IPv6 address test failed");

}