예제 #1
0
static size_t
finish_check (StunAgent *agent, StunMessage *msg)
{
  uint8_t buf[STUN_MAX_MESSAGE_SIZE + 8];
  size_t len;
  uint16_t plen;
  StunMessage msg2 = {0};
  msg2.agent = msg->agent;
  msg2.buffer = buf;
  msg2.buffer_len = sizeof(buf);
  memcpy (msg2.buffer, msg->buffer, sizeof(buf) > msg->buffer_len ? msg->buffer_len : sizeof(buf));

  len = stun_agent_finish_message (agent, msg, NULL, 0);

  if (len <= 0)
    fatal ("Cannot finish message");
  dynamic_check (agent, msg, len);

  if (stun_message_find (&msg2, STUN_ATTRIBUTE_MESSAGE_INTEGRITY, &plen) != NULL)
    fatal ("Missing HMAC test failed");

  stun_message_append_string (&msg2, STUN_ATTRIBUTE_USERNAME, (char *) usr);

  len = stun_agent_finish_message (agent, &msg2, pwd, strlen ((char *) pwd));

  if (len <= 0)
    fatal ("Cannot finish message with short-term creds");
  dynamic_check (agent, &msg2, len);

  return len;
}
예제 #2
0
파일: stunagent.c 프로젝트: GYGit/oneteam
size_t stun_agent_build_unknown_attributes_error (StunAgent *agent,
    StunMessage *msg, uint8_t *buffer, size_t buffer_len,
    const StunMessage *request)
{

  unsigned counter;
  uint16_t ids[STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES];

  counter = stun_agent_find_unknowns (agent, request,
      ids, STUN_AGENT_MAX_UNKNOWN_ATTRIBUTES);

  if (stun_agent_init_error (agent, msg, buffer, buffer_len,
          request, STUN_ERROR_UNKNOWN_ATTRIBUTE) == FALSE) {
    return 0;
  }

  /* NOTE: Old RFC3489 compatibility:
   * When counter is odd, duplicate one value for 32-bits padding. */
  if (!stun_message_has_cookie (request) && (counter & 1))
    ids[counter++] = ids[0];

  if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_UNKNOWN_ATTRIBUTES,
          ids, counter * 2) == STUN_MESSAGE_RETURN_SUCCESS) {
    return stun_agent_finish_message (agent, msg, request->key, request->key_len);
  }

  return 0;
}
예제 #3
0
파일: bind.c 프로젝트: AlertMe/libnice
size_t stun_usage_bind_create (StunAgent *agent, StunMessage *msg,
    uint8_t *buffer, size_t buffer_len)
{
  stun_agent_init_request (agent, msg, buffer, buffer_len, STUN_BINDING);

  return stun_agent_finish_message (agent, msg, NULL, 0);
}
예제 #4
0
파일: bind.c 프로젝트: AlertMe/libnice
size_t
stun_usage_bind_keepalive (StunAgent *agent, StunMessage *msg,
    uint8_t *buf, size_t len)
{

  stun_agent_init_indication (agent, msg,
      buf, len, STUN_BINDING);
  return stun_agent_finish_message (agent, msg, NULL, 0);
}
예제 #5
0
파일: turn.c 프로젝트: roxlu/krx_rtc
size_t stun_usage_turn_create_refresh (StunAgent *agent, StunMessage *msg,
    uint8_t *buffer, size_t buffer_len,
    StunMessage *previous_response, int32_t lifetime,
    uint8_t *username, size_t username_len,
    uint8_t *password, size_t password_len,
    StunUsageTurnCompatibility compatibility)
{

  if (compatibility != STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 &&
      compatibility != STUN_USAGE_TURN_COMPATIBILITY_RFC5766) {
    return stun_usage_turn_create (agent, msg, buffer, buffer_len,
        previous_response, STUN_USAGE_TURN_REQUEST_PORT_NORMAL, 0, lifetime,
        username, username_len, password, password_len, compatibility);
  }

  stun_agent_init_request (agent, msg, buffer, buffer_len, STUN_REFRESH);
  if (lifetime >= 0) {
    if (stun_message_append32 (msg, STUN_ATTRIBUTE_LIFETIME, lifetime) !=
        STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  if (previous_response) {
    uint8_t *realm;
    uint8_t *nonce;
    uint16_t len;

    realm = (uint8_t *) stun_message_find (previous_response,
        STUN_ATTRIBUTE_REALM, &len);
    if (realm != NULL) {
      if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_REALM, realm, len) !=
          STUN_MESSAGE_RETURN_SUCCESS)
        return 0;
    }
    nonce = (uint8_t *) stun_message_find (previous_response,
        STUN_ATTRIBUTE_NONCE, &len);
    if (nonce != NULL) {
      if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_NONCE, nonce, len) !=
          STUN_MESSAGE_RETURN_SUCCESS)
        return 0;
    }
  }


  if (username != NULL && username_len > 0) {
    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);
}
예제 #6
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);
}
예제 #7
0
파일: ice.c 프로젝트: daviad/MeadTest
size_t
stun_usage_ice_conncheck_create (StunAgent *agent, StunMessage *msg,
                                 uint8_t *buffer, size_t buffer_len,
                                 const uint8_t *username, const size_t username_len,
                                 const uint8_t *password, const size_t password_len,
                                 bool cand_use, bool controlling, uint32_t priority,
                                 uint64_t tie, StunUsageIceCompatibility compatibility)
{
    StunMessageReturn val;
    
    stun_agent_init_request (agent, msg, buffer, buffer_len, STUN_BINDING);
    
    if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_RFC5245) {
        if (cand_use)
        {
            val = stun_message_append_flag (msg, STUN_ATTRIBUTE_USE_CANDIDATE);
            if (val != STUN_MESSAGE_RETURN_SUCCESS)
                return 0;
        }
        
        val = stun_message_append32 (msg, STUN_ATTRIBUTE_PRIORITY, priority);
        if (val != STUN_MESSAGE_RETURN_SUCCESS)
            return 0;
        
        if (controlling)
            val = stun_message_append64 (msg, STUN_ATTRIBUTE_ICE_CONTROLLING, tie);
        else
            val = stun_message_append64 (msg, STUN_ATTRIBUTE_ICE_CONTROLLED, tie);
        if (val != STUN_MESSAGE_RETURN_SUCCESS)
            return 0;
    }
    
    if (username && username_len > 0) {
        val = stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
                                         username, username_len);
        if (val != STUN_MESSAGE_RETURN_SUCCESS)
            return 0;
    }
    
    return stun_agent_finish_message (agent, msg, password, password_len);
    
}
예제 #8
0
파일: ice.c 프로젝트: daviad/MeadTest
static int
stun_bind_error (StunAgent *agent, StunMessage *msg,
                 uint8_t *buf, size_t *plen, const StunMessage *req,
                 StunError code)
{
    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, NULL, 0);
    if (len == 0)
        return 0;
    
    *plen = len;
    stun_debug (" Error response (%u) of %u bytes\n", (unsigned)code,
                (unsigned)*plen);
    return 1;
}
예제 #9
0
파일: turn.c 프로젝트: ChinnaSuhas/ossbuild
size_t stun_usage_turn_create (StunAgent *agent, StunMessage *msg,
    uint8_t *buffer, size_t buffer_len,
    StunMessage *previous_response,
    StunUsageTurnRequestPorts request_props,
    int32_t bandwidth, int32_t lifetime,
    uint8_t *username, size_t username_len,
    uint8_t *password, size_t password_len,
    StunUsageTurnCompatibility compatibility)
{
  stun_agent_init_request (agent, msg, buffer, buffer_len, STUN_ALLOCATE);

  if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_DRAFT9) {
    if (stun_message_append32 (msg, STUN_ATTRIBUTE_REQUESTED_TRANSPORT,
            TURN_REQUESTED_TRANSPORT_UDP) != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
    if (bandwidth >= 0) {
      if (stun_message_append32 (msg, STUN_ATTRIBUTE_BANDWIDTH, bandwidth) !=
          STUN_MESSAGE_RETURN_SUCCESS)
        return 0;
    }
  } else {
    if (stun_message_append32 (msg, STUN_ATTRIBUTE_MAGIC_COOKIE,
            TURN_MAGIC_COOKIE) != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  if (lifetime >= 0) {
    if (stun_message_append32 (msg, STUN_ATTRIBUTE_LIFETIME, lifetime) !=
        STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 &&
      request_props != STUN_USAGE_TURN_REQUEST_PORT_NORMAL) {
    uint32_t req = 0;


    if (request_props & STUN_USAGE_TURN_REQUEST_PORT_EVEN_AND_RESERVE) {
      req |= REQUESTED_PROPS_R;
      req |= REQUESTED_PROPS_E;
    } else if (request_props & STUN_USAGE_TURN_REQUEST_PORT_EVEN) {
      req |= REQUESTED_PROPS_E;
    }

    if (stun_message_append32 (msg, STUN_ATTRIBUTE_REQUESTED_PORT_PROPS,
            req) != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  if (previous_response) {
    uint8_t *realm;
    uint8_t *nonce;
    uint64_t reservation;
    uint16_t len;

    realm = (uint8_t *) stun_message_find (previous_response,
        STUN_ATTRIBUTE_REALM, &len);
    if (realm != NULL) {
      if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_REALM, realm, len) !=
          STUN_MESSAGE_RETURN_SUCCESS)
        return 0;
    }
    nonce = (uint8_t *) stun_message_find (previous_response,
        STUN_ATTRIBUTE_NONCE, &len);
    if (nonce != NULL) {
      if (stun_message_append_bytes (msg, STUN_ATTRIBUTE_NONCE, nonce, len) !=
          STUN_MESSAGE_RETURN_SUCCESS)
        return 0;
    }
    if (stun_message_find64 (previous_response, STUN_ATTRIBUTE_RESERVATION_TOKEN,
            &reservation) == STUN_MESSAGE_RETURN_SUCCESS) {
      if (stun_message_append64 (msg, STUN_ATTRIBUTE_RESERVATION_TOKEN,
              reservation) != STUN_MESSAGE_RETURN_SUCCESS)
        return 0;
    }
  }

  if (username != NULL && username_len > 0) {
    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);
}
예제 #10
0
/** 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);
}
예제 #11
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;
    }
}
예제 #12
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");
}
예제 #13
0
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;
}
예제 #14
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;
}
예제 #15
0
파일: ice.c 프로젝트: Kurento/libnice
size_t
stun_usage_ice_conncheck_create (StunAgent *agent, StunMessage *msg,
    uint8_t *buffer, size_t buffer_len,
    const uint8_t *username, const size_t username_len,
    const uint8_t *password, const size_t password_len,
    bool cand_use, bool controlling, uint32_t priority,
    uint64_t tie, const char *candidate_identifier,
    StunUsageIceCompatibility compatibility)
{
  StunMessageReturn val;

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

  if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_RFC5245 ||
      compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSICE2) {
    if (cand_use)
    {
      val = stun_message_append_flag (msg, STUN_ATTRIBUTE_USE_CANDIDATE);
      if (val != STUN_MESSAGE_RETURN_SUCCESS)
        return 0;
    }

    val = stun_message_append32 (msg, STUN_ATTRIBUTE_PRIORITY, priority);
    if (val != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;

    if (controlling)
      val = stun_message_append64 (msg, STUN_ATTRIBUTE_ICE_CONTROLLING, tie);
    else
      val = stun_message_append64 (msg, STUN_ATTRIBUTE_ICE_CONTROLLED, tie);
    if (val != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  if (username && username_len > 0) {
    val = stun_message_append_bytes (msg, STUN_ATTRIBUTE_USERNAME,
        username, username_len);
    if (val != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSICE2 &&
      candidate_identifier) {
    size_t identifier_len = strlen(candidate_identifier);
    size_t attribute_len = identifier_len;
    int modulo4 = identifier_len % 4;
    uint8_t* buf;

    if (modulo4)
        attribute_len += 4 - modulo4;

    // Avoid a coverify false positive
    assert (attribute_len >= identifier_len);
    buf = malloc(attribute_len);
    memset(buf, 0, attribute_len);
    memcpy(buf, candidate_identifier, identifier_len);

    val = stun_message_append_bytes (msg, STUN_ATTRIBUTE_CANDIDATE_IDENTIFIER,
            buf, attribute_len);

    free(buf);

    if (val != STUN_MESSAGE_RETURN_SUCCESS)
		return 0;

    val = stun_message_append32 (msg,
        STUN_ATTRIBUTE_MS_IMPLEMENTATION_VERSION, 2);

    if (val != STUN_MESSAGE_RETURN_SUCCESS)
      return 0;
  }

  return stun_agent_finish_message (agent, msg, password, password_len);

}
예제 #16
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;
  }
}
예제 #17
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;
}
예제 #18
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;
}
예제 #19
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);
}
예제 #20
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;
}
예제 #21
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.");
}