コード例 #1
0
ファイル: test-format.c プロジェクト: AlertMe/libnice
static void
check_af (const char *name, int family, socklen_t addrlen)
{
  struct sockaddr_storage addr;
  uint8_t buf[100];
  StunAgent agent;
  StunMessage msg;
  uint16_t known_attributes[] = {STUN_ATTRIBUTE_USERNAME, STUN_ATTRIBUTE_MESSAGE_INTEGRITY, STUN_ATTRIBUTE_ERROR_CODE, 0};

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

  assert (addrlen <= sizeof (addr));

  memset (&addr, 0, sizeof (addr));
  stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);

  if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
          (struct sockaddr *) &addr, addrlen) !=
      STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS)
    fatal ("Unknown address family test failed");
  if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
          &addr, addrlen) !=
      STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS)
    fatal ("Unknown address family xor test failed");

  addr.ss_family = family;
  if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
          (struct sockaddr *) &addr, addrlen - 1) !=
      STUN_MESSAGE_RETURN_INVALID)
    fatal ("Too small %s sockaddr test failed", name);

  if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
          &addr, addrlen - 1) != STUN_MESSAGE_RETURN_INVALID)
    fatal ("Too small %s sockaddr xor test failed", name);

  if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
          (struct sockaddr *) &addr, addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
    fatal ("%s sockaddr test failed", name);

  if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
          &addr, addrlen) != STUN_MESSAGE_RETURN_SUCCESS)
    fatal ("%s sockaddr xor test failed", name);
}
コード例 #2
0
ファイル: turn.c プロジェクト: roxlu/krx_rtc
size_t stun_usage_turn_create_permission (StunAgent *agent, StunMessage *msg,
    uint8_t *buffer, size_t buffer_len,
    uint8_t *username, size_t username_len,
    uint8_t *password, size_t password_len,
    uint8_t *realm, size_t realm_len,
    uint8_t *nonce, size_t nonce_len,
    struct sockaddr *peer,
    StunUsageTurnCompatibility compatibility)
{
  if (!peer)
    return 0;

  stun_agent_init_request (agent, msg, buffer, buffer_len,
      STUN_CREATEPERMISSION);

  /* PEER address */
  if (stun_message_append_xor_addr (msg, STUN_ATTRIBUTE_XOR_PEER_ADDRESS,
          peer, sizeof(*peer)) != STUN_MESSAGE_RETURN_SUCCESS) {
    return 0;
  }

  /* nonce */
  if (nonce != NULL) {
    if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_NONCE,
            nonce, nonce_len) != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  /* realm */
  if (realm != NULL) {
    if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_REALM,
            realm, realm_len) != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  /* username */
  if (username != NULL) {
    if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
            username, username_len) != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  return stun_agent_finish_message (agent, msg, password, password_len);
}
コード例 #3
0
ファイル: test-format.c プロジェクト: AlertMe/libnice
int main (void)
{
  uint8_t buf[100];
  size_t len;
  union {
    struct sockaddr_storage storage;
    struct sockaddr addr;
  } addr;

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

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

  /* Request formatting test */
  stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
  finish_check (&agent, &msg);
  if (memcmp (buf, "\x00\x01", 2))
    fatal ("Request formatting test failed");

  /* Response formatting test */
  stun_agent_init_response (&agent, &msg, buf, sizeof (buf), &msg);
  finish_check (&agent, &msg);
  if (memcmp (buf, "\x01\x01", 2))
    fatal ("Response formatting test failed");

  /* Error formatting test */
  stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
  finish_check (&agent, &msg);
  if (!stun_agent_init_error (&agent, &msg, buf, sizeof (buf), &msg, 400))
    fatal ("Error initialization test failed");
  finish_check (&agent, &msg);
  if (memcmp (buf, "\x01\x11", 2))
    fatal ("Error formatting test failed");
  /* Unknown error formatting test */
  stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);
  finish_check (&agent, &msg);
  if (!stun_agent_init_error (&agent, &msg, buf, sizeof (buf), &msg, 666))
    fatal ("Unknown error initialization test failed");
  finish_check (&agent, &msg);
  if (memcmp (buf, "\x01\x11", 2))
    fatal ("Unknown error formatting test failed");

  /* Overflow tests */
  stun_agent_init_request (&agent, &msg, buf, sizeof(buf), STUN_BINDING);

  for (len = 0;
       stun_message_append_flag (&msg, 0xffff) !=
           STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE;
       len += 4)
  {
    if (len > 0xffff)
      fatal ("Overflow protection test failed");
  }

  if (stun_message_append32 (&msg, 0xffff, 0x12345678) !=
      STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
    fatal ("Double-word overflow test failed");
  if (stun_message_append64 (&msg, 0xffff,
          0x123456789abcdef0) != STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
    fatal ("Quad-word overflow test failed");
  if (stun_message_append_string (&msg, 0xffff, "foobar") !=
      STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
    fatal ("String overflow test failed");

  memset (&addr, 0, sizeof (addr));
  addr.addr.sa_family = AF_INET;
#ifdef HAVE_SS_LEN
  addr.addr.ss_len = sizeof (addr);
#endif
  if (stun_message_append_xor_addr (&msg, 0xffff, &addr.storage,
          sizeof (addr)) != STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE)
    fatal ("Address overflow test failed");
  len = sizeof (msg);
  if (stun_agent_finish_message (&agent, &msg, NULL, 0) != 0)
    fatal ("Fingerprint overflow test failed");
  if (stun_agent_finish_message (&agent, &msg, pwd, strlen ((char *) pwd)) != 0)
    fatal ("Message integrity overflow test failed");

  /* Address attributes tests */
  check_af ("IPv4", AF_INET, sizeof (struct sockaddr_in));
#ifdef AF_INET6
  check_af ("IPv6", AF_INET6, sizeof (struct sockaddr_in6));
#endif

  return 0;
}
コード例 #4
0
ファイル: test-new-dribble.c プロジェクト: Kurento/libnice
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;
}
コード例 #5
0
ファイル: ice.c プロジェクト: daviad/MeadTest
StunUsageIceReturn
stun_usage_ice_conncheck_create_reply (StunAgent *agent, StunMessage *req,
                                       StunMessage *msg, uint8_t *buf, size_t *plen,
                                       const struct sockaddr *src, socklen_t srclen,
                                       bool *control, uint64_t tie,
                                       StunUsageIceCompatibility compatibility)
{
    const char *username = NULL;
    uint16_t username_len;
    size_t len = *plen;
    uint64_t q;
    StunMessageReturn val = STUN_MESSAGE_RETURN_SUCCESS;
    StunUsageIceReturn ret = STUN_USAGE_ICE_RETURN_SUCCESS;
    
    
#define err( code ) \
stun_bind_error (agent, msg, buf, &len, req, code); \
*plen = len
    
    *plen = 0;
    stun_debug ("STUN Reply (buffer size = %u)...\n", (unsigned)len);
    
    if (stun_message_get_class (req) != STUN_REQUEST)
    {
        stun_debug (" Unhandled non-request (class %u) message.\n",
                    stun_message_get_class (req));
        return STUN_USAGE_ICE_RETURN_INVALID_REQUEST;
    }
    
    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 STUN_USAGE_ICE_RETURN_INVALID_METHOD;
    }
    
    /* Role conflict handling */
    assert (control != NULL);
    if (stun_message_find64 (req, *control ? STUN_ATTRIBUTE_ICE_CONTROLLING
                             : STUN_ATTRIBUTE_ICE_CONTROLLED, &q) == STUN_MESSAGE_RETURN_SUCCESS)
    {
        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 = STUN_USAGE_ICE_RETURN_ROLE_CONFLICT;
        }
        else
        {
            stun_debug (" staying \"controll%s\" (sending error)\n",
                        *control ? "ing" : "ed");
            err (STUN_ERROR_ROLE_CONFLICT);
            return STUN_USAGE_ICE_RETURN_SUCCESS;
        }
    } else {
        stun_debug ("STUN Role not specified by peer!\n");
    }
    
    if (stun_agent_init_response (agent, msg, buf, len, req) == FALSE) {
        stun_debug ("Unable to create response\n");
        goto failure;
    }
    if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) {
        StunTransactionId transid;
        uint32_t magic_cookie;
        stun_message_id (msg, transid);
        magic_cookie = *((uint32_t *) transid);
        
        val = stun_message_append_xor_addr_full (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
                                                 src, srclen, htonl (magic_cookie));
    } else if (stun_message_has_cookie (msg)) {
        val = stun_message_append_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
                                            src, srclen);
    } else {
        val = stun_message_append_addr (msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
                                        src, srclen);
    }
    
    if (val != STUN_MESSAGE_RETURN_SUCCESS) {
        stun_debug (" Mapped address problem: %d\n", val);
        goto failure;
    }
    
    username = (const char *)stun_message_find (req,
                                                STUN_ATTRIBUTE_USERNAME, &username_len);
    if (username) {
        val = stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
                                         username, username_len);
    }
    
    if (val != STUN_MESSAGE_RETURN_SUCCESS) {
        stun_debug ("Error appending username: %d\n", val);
        goto failure;
    }
    
    
    
    /* the stun agent will automatically use the password of the request */
    len = stun_agent_finish_message (agent, msg, NULL, 0);
    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: %d\n", val);
    
    switch (val)
    {
        case STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE:
            return STUN_USAGE_ICE_RETURN_MEMORY_ERROR;
        case STUN_MESSAGE_RETURN_INVALID:
        case STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS:
            return STUN_USAGE_ICE_RETURN_INVALID_ADDRESS;
        default:
            return STUN_USAGE_ICE_RETURN_ERROR;
    }
}
コード例 #6
0
ファイル: stund.c プロジェクト: roxlu/krx_rtc
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;
}
コード例 #7
0
ファイル: stund.c プロジェクト: zsx/ossbuild
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);
}
コード例 #8
0
ファイル: ice.c プロジェクト: Kurento/libnice
StunUsageIceReturn
stun_usage_ice_conncheck_create_reply (StunAgent *agent, StunMessage *req,
    StunMessage *msg, uint8_t *buf, size_t *plen,
    const struct sockaddr_storage *src, socklen_t srclen,
    bool *control, uint64_t tie,
    StunUsageIceCompatibility compatibility)
{
  const char *username = NULL;
  uint16_t username_len;
  size_t len = *plen;
  uint64_t q;
  StunMessageReturn val = STUN_MESSAGE_RETURN_SUCCESS;
  StunUsageIceReturn ret = STUN_USAGE_ICE_RETURN_SUCCESS;


#define err( code ) \
  stun_bind_error (agent, msg, buf, &len, req, code); \
  *plen = len

  *plen = 0;
  stun_debug ("STUN Reply (buffer size = %u)...", (unsigned)len);

  if (stun_message_get_class (req) != STUN_REQUEST)
  {
    stun_debug (" Unhandled non-request (class %u) message.",
         stun_message_get_class (req));
    return STUN_USAGE_ICE_RETURN_INVALID_REQUEST;
  }

  if (stun_message_get_method (req) != STUN_BINDING)
  {
    stun_debug (" Bad request (method %u) message.",
         stun_message_get_method (req));
    err (STUN_ERROR_BAD_REQUEST);
    return STUN_USAGE_ICE_RETURN_INVALID_METHOD;
  }

  /* Role conflict handling */
  assert (control != NULL);
  if (stun_message_find64 (req, *control ? STUN_ATTRIBUTE_ICE_CONTROLLING
          : STUN_ATTRIBUTE_ICE_CONTROLLED, &q) == STUN_MESSAGE_RETURN_SUCCESS)
  {
    /* we have the ice-controlling/controlled attribute,
     * and there's a role conflict
     */
    stun_debug ("STUN Role Conflict detected:");

    /* According to ICE RFC 5245, section 7.2.1.1, we consider the four
     * possible cases when a role conflict is detected: two cases are
     * resolved by switching role locally, and the two other cases are
     * handled by responding with a STUN error.
     */
    if ((tie < q && *control) || (tie >= q && !*control))
    {
      stun_debug (" switching role from \"controll%s\" to \"controll%s\"",
           *control ? "ing" : "ed", *control ? "ed" : "ing");
      *control = !*control;
      ret = STUN_USAGE_ICE_RETURN_ROLE_CONFLICT;
    }
    else
    {
      stun_debug (" staying \"controll%s\" (sending error)",
           *control ? "ing" : "ed");
      err (STUN_ERROR_ROLE_CONFLICT);
      return STUN_USAGE_ICE_RETURN_ROLE_CONFLICT;
    }
  } else {
    if (stun_message_find64 (req, *control ? STUN_ATTRIBUTE_ICE_CONTROLLED
            : STUN_ATTRIBUTE_ICE_CONTROLLING, &q) != STUN_MESSAGE_RETURN_SUCCESS)
    {
      /* we don't have the expected ice-controlling/controlled
       * attribute
       */
      if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_RFC5245 ||
          compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSICE2)
      {
        stun_debug ("STUN Role not specified by peer!");
      }
    }
  }

  if (stun_agent_init_response (agent, msg, buf, len, req) == FALSE) {
    stun_debug ("Unable to create response");
    goto failure;
  }
  if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) {
    union {
      StunTransactionId transid;
      uint32_t magic_cookie;
    } conv;

    stun_message_id (msg, conv.transid);

    val = stun_message_append_xor_addr_full (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
        src, srclen, htonl (conv.magic_cookie));
  } else if (stun_message_has_cookie (msg) &&
      compatibility != STUN_USAGE_ICE_COMPATIBILITY_GOOGLE) {
    val = stun_message_append_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
        src, srclen);
  } else {
    val = stun_message_append_addr (msg, STUN_ATTRIBUTE_MAPPED_ADDRESS,
        (struct sockaddr *) src, srclen);
  }

  if (val != STUN_MESSAGE_RETURN_SUCCESS) {
    stun_debug (" Mapped address problem: %d", val);
    goto failure;
  }

  username = (const char *)stun_message_find (req,
      STUN_ATTRIBUTE_USERNAME, &username_len);
  if (username) {
    val = stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
        username, username_len);
  }

  if (val != STUN_MESSAGE_RETURN_SUCCESS) {
    stun_debug ("Error appending username: %d", val);
    goto failure;
  }

  if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSICE2) {
    val = stun_message_append32 (msg,
        STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION, 2);

    if (val != STUN_MESSAGE_RETURN_SUCCESS) {
      stun_debug ("Error appending implementation version: %d", val);
      goto failure;
    }
  }

  /* the stun agent will automatically use the password of the request */
  len = stun_agent_finish_message (agent, msg, NULL, 0);
  if (len == 0)
    goto failure;

  *plen = len;
  stun_debug (" All done (response size: %u)", (unsigned)len);
  return ret;

failure:
  assert (*plen == 0);
  stun_debug (" Fatal error formatting Response: %d", val);

  switch (val)
  {
    case STUN_MESSAGE_RETURN_NOT_ENOUGH_SPACE:
      return STUN_USAGE_ICE_RETURN_MEMORY_ERROR;
    case STUN_MESSAGE_RETURN_INVALID:
    case STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS:
      return STUN_USAGE_ICE_RETURN_INVALID_ADDRESS;
    case STUN_MESSAGE_RETURN_SUCCESS:
      assert (0);  /* shouldn’t be reached */
    case STUN_MESSAGE_RETURN_NOT_FOUND:
    default:
      return STUN_USAGE_ICE_RETURN_ERROR;
  }
}
コード例 #9
0
ファイル: test_udp_server.c プロジェクト: roxlu/krx_rtc
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;
}