static pj_stun_msg* create_success_response(test_server *test_srv, turn_allocation *alloc, pj_stun_msg *req, pj_pool_t *pool, unsigned lifetime, pj_str_t *auth_key) { pj_stun_msg *resp; pj_str_t tmp; pj_status_t status; /* Create response */ status = pj_stun_msg_create_response(pool, req, 0, NULL, &resp); if (status != PJ_SUCCESS) { return NULL; } /* Add TURN_NONCE */ pj_stun_msg_add_string_attr(pool, resp, PJ_STUN_ATTR_NONCE, pj_cstr(&tmp, TURN_NONCE)); /* Add LIFETIME */ pj_stun_msg_add_uint_attr(pool, resp, PJ_STUN_ATTR_LIFETIME, lifetime); if (lifetime != 0) { /* Add XOR-RELAYED-ADDRESS */ pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_XOR_RELAYED_ADDR, PJ_TRUE, &alloc->alloc_addr, pj_sockaddr_get_len(&alloc->alloc_addr)); /* Add XOR-MAPPED-ADDRESS */ pj_stun_msg_add_sockaddr_attr(pool, resp, PJ_STUN_ATTR_XOR_MAPPED_ADDR, PJ_TRUE, &alloc->client_addr, pj_sockaddr_get_len(&alloc->client_addr)); } /* Add blank MESSAGE-INTEGRITY */ pj_stun_msg_add_msgint_attr(pool, resp); /* Set auth key */ pj_stun_create_key(pool, auth_key, &test_srv->domain, &test_srv->username, PJ_STUN_PASSWD_PLAIN, &test_srv->passwd); return resp; }
static int fingerprint_test_vector() { pj_pool_t *pool; pj_status_t status; unsigned i; int rc = 0; /* To avoid function not referenced warnings */ (void)create_msgint2; (void)create_msgint3; PJ_LOG(3,(THIS_FILE, " draft-denis-behave-rfc3489bis-test-vectors-02")); pool = pj_pool_create(mem, "fingerprint", 1024, 1024, NULL); for (i=0; i<PJ_ARRAY_SIZE(test_vectors); ++i) { struct test_vector *v; pj_stun_msg *ref_msg, *msg; pj_size_t parsed_len; pj_size_t len; unsigned pos; pj_uint8_t buf[1500]; char print[1500]; pj_str_t key; PJ_LOG(3,(THIS_FILE, " Running test %d/%d", i, PJ_ARRAY_SIZE(test_vectors))); v = &test_vectors[i]; /* Print reference message */ PJ_LOG(4,(THIS_FILE, "Reference message PDU:\n%s", print_binary((pj_uint8_t*)v->pdu, v->pdu_len))); /* Try to parse the reference message first */ status = pj_stun_msg_decode(pool, (pj_uint8_t*)v->pdu, v->pdu_len, PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET, &ref_msg, &parsed_len, NULL); if (status != PJ_SUCCESS) { PJ_LOG(1,(THIS_FILE, " Error decoding reference message")); rc = -1010; goto on_return; } if (parsed_len != v->pdu_len) { PJ_LOG(1,(THIS_FILE, " Parsed len error")); rc = -1020; goto on_return; } /* Print the reference message */ pj_stun_msg_dump(ref_msg, print, sizeof(print), NULL); PJ_LOG(4,(THIS_FILE, "Reference message:\n%s", print)); /* Create our message */ msg = v->create(pool, v); if (msg == NULL) { PJ_LOG(1,(THIS_FILE, " Error creating stun message")); rc = -1030; goto on_return; } /* Encode message */ if (v->options & USE_MESSAGE_INTEGRITY) { pj_str_t s1, s2, r; pj_stun_create_key(pool, &key, pj_cstr(&r, v->realm), pj_cstr(&s1, v->username), PJ_STUN_PASSWD_PLAIN, pj_cstr(&s2, v->password)); pj_stun_msg_encode(msg, buf, sizeof(buf), 0, &key, &len); } else { pj_stun_msg_encode(msg, buf, sizeof(buf), 0, NULL, &len); } /* Print our raw message */ PJ_LOG(4,(THIS_FILE, "Message PDU:\n%s", print_binary((pj_uint8_t*)buf, len))); /* Print our message */ pj_stun_msg_dump(msg, print, sizeof(print), NULL); PJ_LOG(4,(THIS_FILE, "Message is:\n%s", print)); /* Compare message length */ if (len != v->pdu_len) { PJ_LOG(1,(THIS_FILE, " Message length mismatch")); rc = -1050; goto on_return; } pos = cmp_buf(buf, (const pj_uint8_t*)v->pdu, len); if (pos != (unsigned)-1) { PJ_LOG(1,(THIS_FILE, " Message mismatch at byte %d", pos)); rc = -1060; goto on_return; } /* Authenticate the request/response */ if (v->options & USE_MESSAGE_INTEGRITY) { if (PJ_STUN_IS_REQUEST(msg->hdr.type)) { pj_stun_auth_cred cred; pj_status_t status; pj_bzero(&cred, sizeof(cred)); cred.type = PJ_STUN_AUTH_CRED_STATIC; cred.data.static_cred.realm = pj_str(v->realm); cred.data.static_cred.username = pj_str(v->username); cred.data.static_cred.data = pj_str(v->password); cred.data.static_cred.nonce = pj_str(v->nonce); status = pj_stun_authenticate_request(buf, len, msg, &cred, pool, NULL, NULL); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(status, errmsg, sizeof(errmsg)); PJ_LOG(1,(THIS_FILE, " Request authentication failed: %s", errmsg)); rc = -1070; goto on_return; } } else if (PJ_STUN_IS_RESPONSE(msg->hdr.type)) { pj_status_t status; status = pj_stun_authenticate_response(buf, len, msg, &key); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(status, errmsg, sizeof(errmsg)); PJ_LOG(1,(THIS_FILE, " Response authentication failed: %s", errmsg)); rc = -1080; goto on_return; } } } } on_return: pj_pool_release(pool); return rc; }
static int decode_test(void) { unsigned i; pj_pool_t *pool; int rc = 0; pool = pj_pool_create(mem, "decode_test", 1024, 1024, NULL); PJ_LOG(3,(THIS_FILE, " STUN decode test")); for (i=0; i<PJ_ARRAY_SIZE(tests); ++i) { struct test *t = &tests[i]; pj_stun_msg *msg, *msg2; pj_uint8_t buf[1500]; pj_str_t key; pj_size_t len; pj_status_t status; PJ_LOG(3,(THIS_FILE, " %s", t->title)); if (t->pdu) { status = pj_stun_msg_decode(pool, (pj_uint8_t*)t->pdu, t->pdu_len, PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET, &msg, NULL, NULL); /* Check expected decode result */ if (t->expected_status != status) { PJ_LOG(1,(THIS_FILE, " expecting status %d, got %d", t->expected_status, status)); rc = -10; goto on_return; } } else { msg = t->create(pool); status = PJ_SUCCESS; } if (status != PJ_SUCCESS) continue; /* Try to encode message */ pj_stun_create_key(pool, &key, NULL, &USERNAME, PJ_STUN_PASSWD_PLAIN, &PASSWORD); status = pj_stun_msg_encode(msg, buf, sizeof(buf), 0, &key, &len); if (status != PJ_SUCCESS) { PJ_LOG(1,(THIS_FILE, " encode error: %s", err(status))); rc = -40; goto on_return; } /* Try to decode it once more */ status = pj_stun_msg_decode(pool, buf, len, PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET, &msg2, NULL, NULL); if (status != PJ_SUCCESS) { PJ_LOG(1,(THIS_FILE, " subsequent decoding failed: %s", err(status))); rc = -50; goto on_return; } /* Verify */ if (t->verify) { rc = t->verify(msg); if (rc != 0) { goto on_return; } } } on_return: pj_pool_release(pool); if (rc == 0) PJ_LOG(3,(THIS_FILE, "...success!")); return rc; }