uint32_t stun_usage_ice_conncheck_priority (const StunMessage *msg) { uint32_t value; if (stun_message_find32 (msg, STUN_ATTRIBUTE_PRIORITY, &value) != STUN_MESSAGE_RETURN_SUCCESS) return 0; return value; }
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; }
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; }
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; }
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; }
/* Tests for message attribute parsing */ static void test_attribute (void) { static const uint8_t acme[] = {0x04, 0x55, 0x00, 0x6C, // <-- update message length if needed!! 0x21, 0x12, 0xA4, 0x42, // cookie 0x76, 0x54, 0x32, 0x10, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, /* FF01: empty */ 0xff, 0x01, 0x00, 0x00, /* FF02: address of unknown family, 32-bits */ 0xff, 0x02, 0x00, 0x04, 0x41, 0x42, 0x43, 0x44, /* FF03: too short IPv6 address */ 0xff, 0x03, 0x00, 0x06, 0x00, 0x02, 0x12, 0x34, 0x20, 0x01, 0x0d, 0xb8, /* FF04: valid IPv4 address, 64-bits */ 0xff, 0x04, 0x00, 0x08, 0x00, 0x01, 0x12, 0x34, 0xc0, 0x00, 0x02, 0x01, /* FF05: too long IPv4 address */ 0xff, 0x05, 0x00, 0x0A, 0x00, 0x01, 0x12, 0x34, 0xc0, 0x00, 0x02, 0x01, 0x66, 0x60, 0x00, 0x00, /* FF06: valid xor'd IPv6 address, 160-bits */ 0xff, 0x06, 0x00, 0x14, 0x00, 0x02, 0x12, 0x34, 0x01, 0x13, 0xa9, 0xfa, 0xa8, 0xf9, 0x8c, 0xff, 0x20, 0x26, 0x74, 0x48, 0x8c, 0x9a, 0xec, 0xfd, /* dummy USERNAME header */ 0x00, 0x06, 0x00, 0x04, 0x41, 0x42, 0x43, 0x44, /* MESSAGE-INTEGRITY attribute */ 0x00, 0x08, 0x00, 0x14, 0x0b, 0xc4, 0xb2, 0x0c, 0x94, 0x58, 0xbb, 0x25, 0xa3, 0x22, 0x1a, 0xc8, 0xe1, 0x87, 0x32, 0x36, 0x3a, 0xfc, 0xe2, 0xc3}; union { struct sockaddr sa; struct sockaddr_in6 s6; } addr; socklen_t addrlen; uint32_t dword; uint64_t qword; char str[STUN_MAX_STR]; StunAgent agent; StunMessage msg; uint16_t known_attributes[] = {STUN_ATTRIBUTE_MESSAGE_INTEGRITY, STUN_ATTRIBUTE_USERNAME, 0}; printf ("Attribute test message length: %lu\n", sizeof (acme)); stun_agent_init (&agent, known_attributes, STUN_COMPATIBILITY_RFC5389, STUN_AGENT_USAGE_SHORT_TERM_CREDENTIALS); if (stun_agent_validate (&agent, &msg, acme, sizeof(acme), NULL, NULL) != STUN_VALIDATION_UNAUTHORIZED) fatal ("Unauthorized validation failed"); if (stun_agent_validate (&agent, &msg, acme, sizeof(acme), test_attribute_validater, "bad__guy") != STUN_VALIDATION_UNAUTHORIZED) fatal ("invalid password validation failed"); if (stun_agent_validate (&agent, &msg, acme, sizeof(acme), test_attribute_validater, "good_guy") != STUN_VALIDATION_SUCCESS) fatal ("good password validation failed"); if (stun_message_has_attribute (&msg, 0xff00)) fatal ("Absent attribute test failed"); if (!stun_message_has_attribute (&msg, 0xff01)) fatal ("Present attribute test failed"); if (stun_message_find_flag (&msg, 0xff00) != STUN_MESSAGE_RETURN_NOT_FOUND) fatal ("Absent flag test failed"); if (stun_message_find_flag (&msg, 0xff01) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("Flag test failed"); if (stun_message_find_flag (&msg, 0xff02) != STUN_MESSAGE_RETURN_INVALID) fatal ("Too big flag test failed"); if (stun_message_find32 (&msg, 0xff00, &dword) != STUN_MESSAGE_RETURN_NOT_FOUND) fatal ("Absent dword test failed"); if (stun_message_find32 (&msg, 0xff01, &dword) != STUN_MESSAGE_RETURN_INVALID) fatal ("Bad dword test failed"); if (stun_message_find32 (&msg, 0xff02, &dword) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("Double-word test failed"); if (stun_message_find64 (&msg, 0xff00, &qword) != STUN_MESSAGE_RETURN_NOT_FOUND) fatal ("Absent qword test failed"); if (stun_message_find64 (&msg, 0xff01, &qword) != STUN_MESSAGE_RETURN_INVALID) fatal ("Bad qword test failed"); if (stun_message_find64 (&msg, 0xff04, &qword) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("Quad-word test failed"); if (stun_message_find_string (&msg, 0xff00, str, STUN_MAX_CP) != STUN_MESSAGE_RETURN_NOT_FOUND) fatal ("Absent string test failed"); if ((stun_message_find_string (&msg, 0xff02, str, STUN_MAX_CP) != STUN_MESSAGE_RETURN_SUCCESS) || strcmp (str, "ABCD")) fatal ("String test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff01, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_INVALID) fatal ("Too short addres test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff02, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_UNSUPPORTED_ADDRESS) fatal ("Unknown address family test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff03, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_INVALID) fatal ("Too short IPv6 address test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff04, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS) fatal ("IPv4 address test failed"); addrlen = sizeof (addr); if (stun_message_find_addr (&msg, 0xff05, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_INVALID) fatal ("Too big IPv4 address test failed"); addrlen = sizeof (addr); if (stun_message_find_xor_addr (&msg, 0xff06, &addr.sa, &addrlen) != STUN_MESSAGE_RETURN_SUCCESS || memcmp (&addr.s6.sin6_addr, "\x20\x01\x0d\xb8""\xde\xad\xbe\xef" "\xde\xfa\xce\xd0""\xfa\xce\xde\xed", 16)) fatal ("IPv6 address test failed"); }