Esempio n. 1
0
File: turn.c Progetto: roxlu/krx_rtc
StunUsageTurnReturn stun_usage_turn_refresh_process (StunMessage *msg,
    uint32_t *lifetime, StunUsageTurnCompatibility compatibility)
{
  int code = -1;
  StunUsageTurnReturn ret = STUN_USAGE_TURN_RETURN_RELAY_SUCCESS;

  if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_DRAFT9 ||
      compatibility == STUN_USAGE_TURN_COMPATIBILITY_RFC5766) {
    if (stun_message_get_method (msg) != STUN_REFRESH)
      return STUN_USAGE_TURN_RETURN_INVALID;
  } else {
    if (stun_message_get_method (msg) != STUN_ALLOCATE)
      return STUN_USAGE_TURN_RETURN_INVALID;
  }

  switch (stun_message_get_class (msg))
  {
    case STUN_REQUEST:
    case STUN_INDICATION:
      return STUN_USAGE_TURN_RETURN_INVALID;

    case STUN_RESPONSE:
      break;

    case STUN_ERROR:
      if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) {
        /* missing ERROR-CODE: ignore message */
        return STUN_USAGE_TURN_RETURN_INVALID;
      }

      return STUN_USAGE_TURN_RETURN_ERROR;

    default:
      /* Fall through. */
      break;
  }

  stun_message_find32 (msg, STUN_ATTRIBUTE_LIFETIME, lifetime);

  stun_debug ("TURN Refresh successful!\n");
  return ret;

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

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

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

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

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

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

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

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

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

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

  assert (valid == STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE);

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

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

  assert (valid == STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST);

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

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

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

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

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

  /* Invalid socket address */
  assert (stun_agent_init_request (&agent, &req, req_buf, sizeof(req_buf), STUN_BINDING));
  val = stun_message_append_string (&req, STUN_ATTRIBUTE_USERNAME,
      (char *) ufrag);
  assert (val == STUN_MESSAGE_RETURN_SUCCESS);
  rlen = stun_agent_finish_message (&agent, &req, pass, pass_len);
  assert (rlen > 0);

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

  addr.ip4.sin_family = AF_INET;

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


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

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

  len = sizeof (resp_buf);
  control = false;
  val2 = stun_usage_ice_conncheck_create_reply (&agent, &req,
      &resp, resp_buf, &len, &addr.storage,
      sizeof (addr.ip4), &control, tie, STUN_USAGE_ICE_COMPATIBILITY_RFC5245);
  assert (val2 == STUN_USAGE_ICE_RETURN_SUCCESS);
  assert (len > 0);
  assert (control == false);
  assert (stun_agent_validate (&agent, &resp, resp_buf, len,
          stun_agent_default_validater, validater_data) == STUN_VALIDATION_SUCCESS);
  assert (stun_message_get_class (&resp) == STUN_ERROR);
  stun_message_find_error (&resp, &code);
  assert (code == STUN_ERROR_ROLE_CONFLICT);


  return 0;
}
Esempio n. 3
0
StunValidationStatus stun_agent_validate (StunAgent *agent, StunMessage *msg,
    const uint8_t *buffer, size_t buffer_len,
    StunMessageIntegrityValidate validater, void * validater_data)
{
  StunTransactionId msg_id;
  uint32_t fpr;
  uint32_t crc32;
  int len;
  uint8_t *username = NULL;
  uint16_t username_len;
  uint8_t *key = NULL;
  size_t key_len;
  uint8_t *hash;
  uint8_t sha[20];
  uint16_t hlen;
  int sent_id_idx = -1;
  uint16_t unknown;
  int error_code;
  int ignore_credentials = 0;
  uint8_t long_term_key[16];
  bool long_term_key_valid = FALSE;

  len = stun_message_validate_buffer_length (buffer, buffer_len);
  if (len == STUN_MESSAGE_BUFFER_INVALID) {
    return STUN_VALIDATION_NOT_STUN;
  } else if (len == STUN_MESSAGE_BUFFER_INCOMPLETE) {
    return STUN_VALIDATION_INCOMPLETE_STUN;
  } else if (len != (int) buffer_len) {
    return STUN_VALIDATION_NOT_STUN;
  }

  msg->buffer = (uint8_t *) buffer;
  msg->buffer_len = buffer_len;
  msg->agent = agent;
  msg->key = NULL;
  msg->key_len = 0;
  msg->long_term_valid = FALSE;

  /* TODO: reject it or not ? */
  if ((agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
          agent->compatibility == STUN_COMPATIBILITY_WLM2009) &&
      !stun_message_has_cookie (msg)) {
      stun_debug ("STUN demux error: no cookie!\n");
      return STUN_VALIDATION_BAD_REQUEST;
  }

  if ((agent->compatibility == STUN_COMPATIBILITY_RFC5389 ||
          agent->compatibility == STUN_COMPATIBILITY_WLM2009) &&
      agent->usage_flags & STUN_AGENT_USAGE_USE_FINGERPRINT) {
    /* Looks for FINGERPRINT */
    if (stun_message_find32 (msg, STUN_ATTRIBUTE_FINGERPRINT, &fpr) !=
        STUN_MESSAGE_RETURN_SUCCESS) {
      stun_debug ("STUN demux error: no FINGERPRINT attribute!\n");
      return STUN_VALIDATION_BAD_REQUEST;
    }
    /* Checks FINGERPRINT */
    crc32 = stun_fingerprint (msg->buffer, stun_message_length (msg),
        agent->compatibility == STUN_COMPATIBILITY_WLM2009);
    fpr = ntohl (fpr);
    if (fpr != crc32) {
      stun_debug ("STUN demux error: bad fingerprint: 0x%08x,"
          " expected: 0x%08x!\n", fpr, crc32);
      return STUN_VALIDATION_BAD_REQUEST;
    }

    stun_debug ("STUN demux: OK!\n");
  }

  if (stun_message_get_class (msg) == STUN_RESPONSE ||
      stun_message_get_class (msg) == STUN_ERROR) {
    stun_message_id (msg, msg_id);
    for (sent_id_idx = 0; sent_id_idx < STUN_AGENT_MAX_SAVED_IDS; sent_id_idx++) {
      if (agent->sent_ids[sent_id_idx].valid == TRUE &&
          agent->sent_ids[sent_id_idx].method == stun_message_get_method (msg) &&
          memcmp (msg_id, agent->sent_ids[sent_id_idx].id,
              sizeof(StunTransactionId)) == 0) {

        key = agent->sent_ids[sent_id_idx].key;
        key_len = agent->sent_ids[sent_id_idx].key_len;
        memcpy (long_term_key, agent->sent_ids[sent_id_idx].long_term_key,
            sizeof(long_term_key));
        long_term_key_valid = agent->sent_ids[sent_id_idx].long_term_valid;
        break;
      }
    }
    if (sent_id_idx == STUN_AGENT_MAX_SAVED_IDS) {
      return STUN_VALIDATION_UNMATCHED_RESPONSE;
    }
  }

  ignore_credentials =
      (agent->usage_flags & STUN_AGENT_USAGE_IGNORE_CREDENTIALS) ||
      (stun_message_get_class (msg) == STUN_ERROR &&
       stun_message_find_error (msg, &error_code) ==
          STUN_MESSAGE_RETURN_SUCCESS &&
       (error_code == 400 || error_code == 401)) ||
      (stun_message_get_class (msg) == STUN_INDICATION &&
       (agent->usage_flags & STUN_AGENT_USAGE_NO_INDICATION_AUTH));

  if (key == NULL &&
      ignore_credentials == 0 &&
      (stun_message_get_class (msg) == STUN_REQUEST ||
       stun_message_get_class (msg) == STUN_INDICATION) &&
      (((agent->usage_flags & STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS) &&
       (!stun_message_has_attribute (msg, STUN_ATTRIBUTE_USERNAME) ||
        !stun_message_has_attribute (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY))) ||
      ((agent->usage_flags & STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS) &&
        stun_message_get_class (msg) == STUN_REQUEST &&
        (!stun_message_has_attribute (msg, STUN_ATTRIBUTE_USERNAME) ||
         !stun_message_has_attribute (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY) ||
         !stun_message_has_attribute (msg, STUN_ATTRIBUTE_NONCE) ||
         !stun_message_has_attribute (msg, STUN_ATTRIBUTE_REALM))) ||
       ((agent->usage_flags & STUN_AGENT_USAGE_IGNORE_CREDENTIALS) == 0 &&
         stun_message_has_attribute (msg, STUN_ATTRIBUTE_USERNAME) &&
         !stun_message_has_attribute (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY)))) {
        return STUN_VALIDATION_UNAUTHORIZED_BAD_REQUEST;
  }

  if (stun_message_has_attribute (msg, STUN_ATTRIBUTE_MESSAGE_INTEGRITY) &&
      ((key == NULL && ignore_credentials == 0) ||
          (agent->usage_flags & STUN_AGENT_USAGE_FORCE_VALIDATER))) {
    username_len = 0;
    username = (uint8_t *) stun_message_find (msg, STUN_ATTRIBUTE_USERNAME,
        &username_len);
    if (validater == NULL ||
        validater (agent, msg, username, username_len,
            &key, &key_len, validater_data) == FALSE) {
      return STUN_VALIDATION_UNAUTHORIZED;
    }
  }

  if (ignore_credentials == 0 && key != NULL && key_len > 0) {
    hash = (uint8_t *) stun_message_find (msg,
        STUN_ATTRIBUTE_MESSAGE_INTEGRITY, &hlen);

    if (hash) {
      /* We must give the size from start to the end of the attribute
         because you might have a FINGERPRINT attribute after it... */
      if (agent->usage_flags & STUN_AGENT_USAGE_LONG_TERM_CREDENTIALS) {
        uint8_t *realm = NULL;
        uint8_t *username = NULL;
        uint16_t realm_len;
        uint16_t username_len;
        uint8_t md5[16];

        if (long_term_key_valid) {
          memcpy (md5, long_term_key, sizeof (md5));
        } else {
          realm = (uint8_t *) stun_message_find (msg,  STUN_ATTRIBUTE_REALM, &realm_len);
          username = (uint8_t *) stun_message_find (msg,
              STUN_ATTRIBUTE_USERNAME, &username_len);
          if (username == NULL || realm == NULL) {
            return STUN_VALIDATION_UNAUTHORIZED;
          }
          stun_hash_creds (realm, realm_len,
              username,  username_len,
              key, key_len, md5);
        }

        memcpy (msg->long_term_key, md5, sizeof(md5));
        msg->long_term_valid = TRUE;

        if (agent->compatibility == STUN_COMPATIBILITY_RFC3489) {
          stun_sha1 (msg->buffer, hash + 20 - msg->buffer, hash - msg->buffer,
              sha, md5, sizeof(md5), TRUE);
        } else if (agent->compatibility == STUN_COMPATIBILITY_WLM2009) {
          stun_sha1 (msg->buffer, hash + 20 - msg->buffer,
              stun_message_length (msg) - 20, sha, md5, sizeof(md5), TRUE);
        } else {
          stun_sha1 (msg->buffer, hash + 20 - msg->buffer,
              hash - msg->buffer, sha, md5, sizeof(md5), FALSE);
        }
      } else {
        if (agent->compatibility == STUN_COMPATIBILITY_RFC3489) {
          stun_sha1 (msg->buffer, hash + 20 - msg->buffer, hash - msg->buffer,
              sha, key, key_len, TRUE);
        } else if (agent->compatibility == STUN_COMPATIBILITY_WLM2009) {
          stun_sha1 (msg->buffer, hash + 20 - msg->buffer,
              stun_message_length (msg) - 20, sha, key, key_len, TRUE);
        } else {
          stun_sha1 (msg->buffer, hash + 20 - msg->buffer,
              hash - msg->buffer, sha, key, key_len, FALSE);
        }
      }

      stun_debug (" Message HMAC-SHA1 fingerprint:");
      stun_debug ("\nkey     : ");
      stun_debug_bytes (key, key_len);
      stun_debug ("\n  expected: ");
      stun_debug_bytes (sha, sizeof (sha));
      stun_debug ("\n  received: ");
      stun_debug_bytes (hash, sizeof (sha));
      stun_debug ("\n");

      if (memcmp (sha, hash, sizeof (sha)))  {
        stun_debug ("STUN auth error: SHA1 fingerprint mismatch!\n");
        return STUN_VALIDATION_UNAUTHORIZED;
      }

      stun_debug ("STUN auth: OK!\n");
      msg->key = key;
      msg->key_len = key_len;
    } else if (!(stun_message_get_class (msg) == STUN_ERROR &&
        stun_message_find_error (msg, &error_code) ==
            STUN_MESSAGE_RETURN_SUCCESS &&
        (error_code == 400 || error_code == 401))) {
      stun_debug ("STUN auth error: No message integrity attribute!\n");
      return STUN_VALIDATION_UNAUTHORIZED;
    }
  }


  if (sent_id_idx != -1 && sent_id_idx < STUN_AGENT_MAX_SAVED_IDS) {
    agent->sent_ids[sent_id_idx].valid = FALSE;
  }

  if (stun_agent_find_unknowns (agent, msg, &unknown, 1) > 0) {
    if (stun_message_get_class (msg) == STUN_REQUEST)
      return STUN_VALIDATION_UNKNOWN_REQUEST_ATTRIBUTE;
    else
      return STUN_VALIDATION_UNKNOWN_ATTRIBUTE;
  }
  return STUN_VALIDATION_SUCCESS;

}
Esempio n. 4
0
StunUsageTurnReturn stun_usage_turn_process (StunMessage *msg,
    struct sockaddr *relay_addr, socklen_t *relay_addrlen,
    struct sockaddr *addr, socklen_t *addrlen,
    struct sockaddr *alternate_server, socklen_t *alternate_server_len,
    uint32_t *bandwidth, uint32_t *lifetime,
    StunUsageTurnCompatibility compatibility)
{
  int val, code = -1;
  StunUsageTurnReturn ret = STUN_USAGE_TURN_RETURN_RELAY_SUCCESS;

  if (stun_message_get_method (msg) != STUN_ALLOCATE)
    return STUN_USAGE_TURN_RETURN_INVALID;

  switch (stun_message_get_class (msg))
  {
    case STUN_REQUEST:
    case STUN_INDICATION:
      return STUN_USAGE_TURN_RETURN_INVALID;

    case STUN_RESPONSE:
      break;

    case STUN_ERROR:
      if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) {
        /* missing ERROR-CODE: ignore message */
        return STUN_USAGE_TURN_RETURN_INVALID;
      }

      /* NOTE: currently we ignore unauthenticated messages if the context
       * is authenticated, for security reasons. */
      stun_debug (" STUN error message received (code: %d)\n", code);

      /* ALTERNATE-SERVER mechanism */
      if ((code / 100) == 3) {
        if (alternate_server && alternate_server_len) {
          if (stun_message_find_addr (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER,
                  alternate_server, alternate_server_len) !=
              STUN_MESSAGE_RETURN_SUCCESS) {
            stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute\n");
            return STUN_USAGE_TURN_RETURN_ERROR;
          }
        } else {
          if (!stun_message_has_attribute (msg,
                  STUN_ATTRIBUTE_ALTERNATE_SERVER)) {
            stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute\n");
            return STUN_USAGE_TURN_RETURN_ERROR;
          }
        }

        stun_debug ("Found alternate server\n");
        return STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER;

      }
      return STUN_USAGE_TURN_RETURN_ERROR;
  }

  stun_debug ("Received %u-bytes STUN message\n", stun_message_length (msg));

  if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_DRAFT9) {
    val = stun_message_find_xor_addr (msg,
        STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen);

    if (val == STUN_MESSAGE_RETURN_SUCCESS)
      ret = STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS;
    val = stun_message_find_xor_addr (msg,
        STUN_ATTRIBUTE_RELAY_ADDRESS, relay_addr, relay_addrlen);
    if (val != STUN_MESSAGE_RETURN_SUCCESS) {
      stun_debug (" No RELAYED-ADDRESS: %d\n", val);
      return STUN_USAGE_TURN_RETURN_ERROR;
    }
  } else if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_GOOGLE) {
    val = stun_message_find_addr (msg,
        STUN_ATTRIBUTE_MAPPED_ADDRESS, relay_addr, relay_addrlen);
    if (val != STUN_MESSAGE_RETURN_SUCCESS) {
      stun_debug (" No MAPPED-ADDRESS: %d\n", val);
      return STUN_USAGE_TURN_RETURN_ERROR;
    }
  } else if (compatibility == STUN_USAGE_TURN_COMPATIBILITY_MSN) {
    val = stun_message_find_addr (msg,
        STUN_ATTRIBUTE_MSN_MAPPED_ADDRESS, addr, addrlen);

    if (val == STUN_MESSAGE_RETURN_SUCCESS)
      ret = STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS;

    val = stun_message_find_addr (msg,
        STUN_ATTRIBUTE_MAPPED_ADDRESS, relay_addr, relay_addrlen);
    if (val != STUN_MESSAGE_RETURN_SUCCESS) {
      stun_debug (" No MAPPED-ADDRESS: %d\n", val);
      return STUN_USAGE_TURN_RETURN_ERROR;
    }
  }

  stun_message_find32 (msg, STUN_ATTRIBUTE_LIFETIME, lifetime);
  stun_message_find32 (msg, STUN_ATTRIBUTE_BANDWIDTH, bandwidth);

  stun_debug (" Mapped address found!\n");
  return ret;

}
Esempio n. 5
0
StunUsageIceReturn stun_usage_ice_conncheck_process (StunMessage *msg,
                                                     struct sockaddr *addr, socklen_t *addrlen,
                                                     StunUsageIceCompatibility compatibility)
{
    int code = -1;
    StunMessageReturn val;
    
    if (stun_message_get_method (msg) != STUN_BINDING)
        return STUN_USAGE_ICE_RETURN_INVALID;
    
    switch (stun_message_get_class (msg))
    {
        case STUN_REQUEST:
        case STUN_INDICATION:
            return STUN_USAGE_ICE_RETURN_INVALID;
            
        case STUN_RESPONSE:
            break;
            
        case STUN_ERROR:
            if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) {
                /* missing ERROR-CODE: ignore message */
                return STUN_USAGE_ICE_RETURN_INVALID;
            }
            
            if (code  == STUN_ERROR_ROLE_CONFLICT)
                return STUN_USAGE_ICE_RETURN_ROLE_CONFLICT;
            
            /* NOTE: currently we ignore unauthenticated messages if the context
             * is authenticated, for security reasons. */
            stun_debug (" STUN error message received (code: %d)\n", code);
            
            return STUN_USAGE_ICE_RETURN_ERROR;
    }
    
    stun_debug ("Received %u-bytes STUN message\n", stun_message_length (msg));
    
    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_find_xor_addr_full (msg,
                                               STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen, htonl (magic_cookie));
    } else {
        val = stun_message_find_xor_addr (msg,
                                          STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen);
    }
    if (val != STUN_MESSAGE_RETURN_SUCCESS)
    {
        stun_debug (" No XOR-MAPPED-ADDRESS: %d\n", val);
        val = stun_message_find_addr (msg,
                                      STUN_ATTRIBUTE_MAPPED_ADDRESS, addr, addrlen);
        if (val != STUN_MESSAGE_RETURN_SUCCESS)
        {
            stun_debug (" No MAPPED-ADDRESS: %d\n", val);
            return STUN_USAGE_ICE_RETURN_NO_MAPPED_ADDRESS;
        }
    }
    
    stun_debug ("Mapped address found!\n");
    return STUN_USAGE_ICE_RETURN_SUCCESS;
}
Esempio n. 6
0
StunUsageBindReturn stun_usage_bind_process (StunMessage *msg,
    struct sockaddr *addr, socklen_t *addrlen,
    struct sockaddr *alternate_server, socklen_t *alternate_server_len)
{
  int code = -1;
  StunMessageReturn val;

  if (stun_message_get_method (msg) != STUN_BINDING)
    return STUN_USAGE_BIND_RETURN_INVALID;

  switch (stun_message_get_class (msg))
  {
    case STUN_REQUEST:
    case STUN_INDICATION:
      return STUN_USAGE_BIND_RETURN_INVALID;

    case STUN_RESPONSE:
      break;

    case STUN_ERROR:
      if (stun_message_find_error (msg, &code) != STUN_MESSAGE_RETURN_SUCCESS) {
        /* missing ERROR-CODE: ignore message */
        return STUN_USAGE_BIND_RETURN_INVALID;
      }

      /* NOTE: currently we ignore unauthenticated messages if the context
       * is authenticated, for security reasons. */
      stun_debug (" STUN error message received (code: %d)", code);

      /* ALTERNATE-SERVER mechanism */
      if ((code / 100) == 3) {
        if (alternate_server && alternate_server_len) {
          if (stun_message_find_addr (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER,
                  (struct sockaddr_storage *) alternate_server,
                  alternate_server_len) != STUN_MESSAGE_RETURN_SUCCESS) {
            stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute");
            return STUN_USAGE_BIND_RETURN_ERROR;
          }
        } else {
          if (!stun_message_has_attribute (msg, STUN_ATTRIBUTE_ALTERNATE_SERVER)) {
            stun_debug (" Unexpectedly missing ALTERNATE-SERVER attribute");
            return STUN_USAGE_BIND_RETURN_ERROR;
          }
        }

        stun_debug ("Found alternate server");
        return STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER;

      }
      return STUN_USAGE_BIND_RETURN_ERROR;

    default:
      /* Fall through. */
      break;
  }

  stun_debug ("Received %u-bytes STUN message", stun_message_length (msg));

  val = stun_message_find_xor_addr (msg,
      STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, (struct sockaddr_storage *)addr,
      addrlen);
  if (val != STUN_MESSAGE_RETURN_SUCCESS)
  {
    stun_debug (" No XOR-MAPPED-ADDRESS: %d", val);
    val = stun_message_find_addr (msg,
        STUN_ATTRIBUTE_MAPPED_ADDRESS, (struct sockaddr_storage *)addr,
        addrlen);
    if (val != STUN_MESSAGE_RETURN_SUCCESS)
    {
      stun_debug (" No MAPPED-ADDRESS: %d", val);
      return STUN_USAGE_BIND_RETURN_ERROR;
    }
  }

  stun_debug (" Mapped address found!");
  return STUN_USAGE_BIND_RETURN_SUCCESS;

}