summaryrefslogtreecommitdiff
path: root/pjnath/src/pjnath-test
diff options
context:
space:
mode:
authorBenny Prijono <bennylp@teluu.com>2007-09-18 19:33:33 +0000
committerBenny Prijono <bennylp@teluu.com>2007-09-18 19:33:33 +0000
commit41234fb3ea6190fdf7bebf0d11bc41d578b66934 (patch)
tree845b6ba62a1477e77501189b0221b638cae67af9 /pjnath/src/pjnath-test
parent0b5b5d6d0b9e0c0362c15126bd74176aa1ce5161 (diff)
Ticket #374: Update STUN specification from rfc3489bis-06 to rfc3489bis-10
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@1439 74dad513-b988-da41-8d7b-12977e46ad98
Diffstat (limited to 'pjnath/src/pjnath-test')
-rw-r--r--pjnath/src/pjnath-test/stun.c698
-rw-r--r--pjnath/src/pjnath-test/test.c4
-rw-r--r--pjnath/src/pjnath-test/test.h2
3 files changed, 679 insertions, 25 deletions
diff --git a/pjnath/src/pjnath-test/stun.c b/pjnath/src/pjnath-test/stun.c
index 230e51e7..29a8eb1a 100644
--- a/pjnath/src/pjnath-test/stun.c
+++ b/pjnath/src/pjnath-test/stun.c
@@ -16,42 +16,392 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include "test.h"
-static int decode_test(void)
-{
- /* Invalid message type */
-
- /* Short message */
-
- /* Long, random message */
+#define THIS_FILE "stun.c"
- /* Message length in header is shorter */
+static pj_stun_msg* create1(pj_pool_t*);
+static int verify1(pj_stun_msg*);
+static int verify2(pj_stun_msg*);
+static int verify5(pj_stun_msg*);
- /* Message length in header is longer */
-
- /* Invalid magic */
-
- /* Attribute length is not valid */
+static struct test
+{
+ const char *title;
+ char *pdu;
+ unsigned pdu_len;
+ pj_stun_msg* (*create)(pj_pool_t*);
+ pj_status_t expected_status;
+ int (*verify)(pj_stun_msg*);
+} tests[] =
+{
+ {
+ "Invalid message type",
+ "\x11\x01\x00\x00\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ 20,
+ NULL,
+ PJNATH_EINSTUNMSGTYPE,
+ NULL
+ },
+ {
+ "Short message (1) (partial header)",
+ "\x00\x01",
+ 2,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Short message (2) (partial header)",
+ "\x00\x01\x00\x00\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00",
+ 16,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Short message (3), (missing attribute)",
+ "\x00\x01\x00\x08\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
+ 20,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Short message (4), (partial attribute header)",
+ "\x00\x01\x00\x08\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\x28",
+ 22,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Short message (5), (partial attribute header)",
+ "\x00\x01\x00\x08\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\x28\x00",
+ 23,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Short message (6), (partial attribute header)",
+ "\x00\x01\x00\x08\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\x28\x00\x04",
+ 24,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Short message (7), (partial attribute body)",
+ "\x00\x01\x00\x08\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\x28\x00\x04\x00\x00\x00",
+ 27,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Message length in header is too long",
+ "\x00\x01\xff\xff\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\x28\x00\x04\x00\x00\x00",
+ 27,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Message length in header is shorter",
+ "\x00\x01\x00\x04\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\x28\x00\x04\x00\x00\x00\x00",
+ 28,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Invalid magic",
+ "\x00\x01\x00\x08\x00\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\x28\x00\x04\x00\x00\x00\x00",
+ 28,
+ NULL,
+ PJ_SUCCESS,
+ NULL
+ },
+ {
+ "Character beyond message",
+ "\x00\x01\x00\x08\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\x28\x00\x04\x00\x00\x00\x00\x0a",
+ 29,
+ NULL,
+ PJNATH_EINSTUNMSGLEN,
+ NULL
+ },
+ {
+ "Respond unknown mandatory attribute with 420 and "
+ "UNKNOWN-ATTRIBUTES attribute",
+ NULL,
+ 0,
+ &create1,
+ 0,
+ &verify1
+ },
+ {
+ "Unknown but non-mandatory should be okay",
+ "\x00\x01\x00\x08\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\xff\x00\x04\x00\x00\x00\x00",
+ 28,
+ NULL,
+ PJ_SUCCESS,
+ &verify2
+ },
+ {
+ "String attr length larger than message",
+ "\x00\x01\x00\x08\x00\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x06\x00\xff\x00\x00\x00\x00",
+ 28,
+ NULL,
+ PJNATH_ESTUNINATTRLEN,
+ NULL
+ },
+ {
+ "Attribute other than FINGERPRINT after MESSAGE-INTEGRITY is allowed",
+ "\x00\x01\x00\x20\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x08\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // M-I
+ "\x80\x24\x00\x04\x00\x00\x00\x00", // REFRESH-INTERVAL
+ 52,
+ NULL,
+ PJ_SUCCESS,
+ NULL
+ },
+ {
+ "Attribute between MESSAGE-INTEGRITY and FINGERPRINT is allowed",
+ "\x00\x01\x00\x28\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x08\x00\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" // M-I
+ "\x80\x24\x00\x04\x00\x00\x00\x00" // REFRESH-INTERVAL
+ "\x80\x28\x00\x04\xc7\xde\xdd\x65", // FINGERPRINT
+ 60,
+ NULL,
+ PJ_SUCCESS,
+ &verify5
+ },
+ {
+ "Attribute past FINGERPRINT is not allowed",
+ "\x00\x01\x00\x10\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x80\x28\x00\x04\x00\x00\x00\x00"
+ "\x80\x24\x00\x04\x00\x00\x00\x00",
+ 36,
+ NULL,
+ PJNATH_ESTUNFINGERPOS,
+ NULL
+ }
+};
+
+static const char *err(pj_status_t status)
+{
+ static char errmsg[PJ_ERR_MSG_SIZE];
+ pj_strerror(status, errmsg, sizeof(errmsg));
+ return errmsg;
+}
- /* Unknown mandatory attribute type should generate error */
+static const pj_str_t USERNAME = {"user", 4};
+static const pj_str_t PASSWORD = {"password", 8};
- /* Unknown but non-mandatory should be okay */
+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;
+ unsigned 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, &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;
+}
- /* String/binary attribute length is larger than the message */
+/* Create 420 response */
+static pj_stun_msg* create1(pj_pool_t *pool)
+{
+ char *pdu = "\x00\x01\x00\x08\x21\x12\xa4\x42"
+ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\xff\x00\x04\x00\x00\x00\x00";
+ unsigned pdu_len = 28;
+ pj_stun_msg *msg, *res;
+ pj_status_t status;
+
+ status = pj_stun_msg_decode(pool, (pj_uint8_t*)pdu, pdu_len,
+ PJ_STUN_IS_DATAGRAM | PJ_STUN_CHECK_PACKET,
+ &msg, NULL, &res);
+ pj_assert(status != PJ_SUCCESS);
+ pj_assert(res != NULL);
+
+ return res;
+}
- /* Valid message with MESSAGE-INTEGRITY */
+/* Error response MUST have ERROR-CODE attribute */
+/* 420 response MUST contain UNKNOWN-ATTRIBUTES */
+static int verify1(pj_stun_msg *msg)
+{
+ pj_stun_errcode_attr *aerr;
+ pj_stun_unknown_attr *aunk;
+
+ if (!PJ_STUN_IS_ERROR_RESPONSE(msg->hdr.type)) {
+ PJ_LOG(1,(THIS_FILE, " expecting error message"));
+ return -100;
+ }
+
+ aerr = (pj_stun_errcode_attr*)
+ pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_ERROR_CODE, 0);
+ if (aerr == NULL) {
+ PJ_LOG(1,(THIS_FILE, " missing ERROR-CODE attribute"));
+ return -110;
+ }
+
+ if (aerr->err_code != 420) {
+ PJ_LOG(1,(THIS_FILE, " expecting 420 error"));
+ return -120;
+ }
+
+ aunk = (pj_stun_unknown_attr*)
+ pj_stun_msg_find_attr(msg, PJ_STUN_ATTR_UNKNOWN_ATTRIBUTES, 0);
+ if (aunk == NULL) {
+ PJ_LOG(1,(THIS_FILE, " missing UNKNOWN-ATTRIBUTE attribute"));
+ return -130;
+ }
+
+ if (aunk->attr_count != 1) {
+ PJ_LOG(1,(THIS_FILE, " expecting one unknown attribute"));
+ return -140;
+ }
+
+ if (aunk->attrs[0] != 0xff) {
+ PJ_LOG(1,(THIS_FILE, " expecting 0xff as unknown attribute"));
+ return -150;
+ }
- /* Valid message with FINGERPRINT */
+ return 0;
+}
- /* Valid message with MESSAGE-INTEGRITY and FINGERPRINT */
+/* Attribute count should be zero since unknown attribute is not parsed */
+static int verify2(pj_stun_msg *msg)
+{
+ if (msg->attr_count != 0) {
+ PJ_LOG(1,(THIS_FILE, " expecting zero attribute count"));
+ return -200;
+ }
+ return 0;
+}
- /* Another attribute not FINGERPRINT exists after MESSAGE-INTEGRITY */
- /* Another attribute exists after FINGERPRINT */
+/* Attribute between MESSAGE-INTEGRITY and FINGERPRINT is allowed */
+static int verify5(pj_stun_msg *msg)
+{
+ if (msg->attr_count != 3) {
+ PJ_LOG(1,(THIS_FILE, " expecting 3 attribute count"));
+ return -500;
+ }
+
+ if (msg->attr[0]->type != PJ_STUN_ATTR_MESSAGE_INTEGRITY) {
+ PJ_LOG(1,(THIS_FILE, " expecting MESSAGE-INTEGRITY"));
+ return -510;
+ }
+ if (msg->attr[1]->type != PJ_STUN_ATTR_REFRESH_INTERVAL) {
+ PJ_LOG(1,(THIS_FILE, " expecting REFRESH-INTERVAL"));
+ return -520;
+ }
+ if (msg->attr[2]->type != PJ_STUN_ATTR_FINGERPRINT) {
+ PJ_LOG(1,(THIS_FILE, " expecting FINGERPRINT"));
+ return -530;
+ }
return 0;
}
+
static int decode_verify(void)
{
/* Decode all attribute types */
@@ -107,12 +457,310 @@ static int auth_test(void)
return 0;
}
+typedef struct test_vector test_vector;
+
+static pj_stun_msg* create_msgint1(pj_pool_t *pool, test_vector *v);
+static pj_stun_msg* create_msgint2(pj_pool_t *pool, test_vector *v);
+
+enum
+{
+ USE_MESSAGE_INTEGRITY = 1,
+ USE_FINGERPRINT = 2
+};
+
+struct test_vector
+{
+ unsigned msg_type;
+ char *tsx_id;
+ char *pdu;
+ unsigned pdu_len;
+ unsigned options;
+ char *username;
+ char *password;
+ pj_stun_msg* (*create)(pj_pool_t*, test_vector*);
+} test_vectors[] =
+{
+ {
+ PJ_STUN_BINDING_REQUEST,
+ "\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae",
+ "\x00\x01\x00\x44\x21\x12\xa4\x42\xb7\xe7"
+ "\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae"
+ "\x00\x24\x00\x04\x6e\x00\x01\xff\x80\x29"
+ "\x00\x08\x93\x2f\xf9\xb1\x51\x26\x3b\x36"
+ "\x00\x06\x00\x09\x65\x76\x74\x6a\x3a\x68"
+ "\x36\x76\x59\x20\x20\x20\x00\x08\x00\x14"
+ "\x62\x4e\xeb\xdc\x3c\xc9\x2d\xd8\x4b\x74"
+ "\xbf\x85\xd1\xc0\xf5\xde\x36\x87\xbd\x33"
+ "\x80\x28\x00\x04\xad\x8a\x85\xff",
+ 88,
+ USE_MESSAGE_INTEGRITY | USE_FINGERPRINT,
+ "evtj:h6vY",
+ "VOkJxbRl1RmTxUk/WvJxBt",
+ &create_msgint1
+ },
+ {
+ PJ_STUN_BINDING_RESPONSE,
+ "\xb7\xe7\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae",
+ "\x01\x01\x00\x3c\x21\x12\xa4\x42\xb7\xe7"
+ "\xa7\x01\xbc\x34\xd6\x86\xfa\x87\xdf\xae"
+ "\x80\x22\x00\x0b\x74\x65\x73\x74\x20\x76"
+ "\x65\x63\x74\x6f\x72\x20\x00\x20\x00\x08"
+ "\x00\x01\xa1\x47\x5e\x12\xa4\x43\x00\x08"
+ "\x00\x14\xab\x4e\x53\x29\x61\x00\x08\x4c"
+ "\x89\xf2\x7c\x69\x30\x33\x5c\xa3\x58\x14"
+ "\xea\x90\x80\x28\x00\x04\xae\x25\x8d\xf2",
+ 80,
+ USE_MESSAGE_INTEGRITY | USE_FINGERPRINT,
+ "evtj:h6vY",
+ "VOkJxbRl1RmTxUk/WvJxBt",
+ &create_msgint2
+ }
+};
+
+
+static char* print_binary(const pj_uint8_t *data, unsigned data_len)
+{
+ static char buf[1500];
+ unsigned length = sizeof(buf);
+ char *p = buf;
+ unsigned i;
+
+ for (i=0; i<data_len;) {
+ unsigned j;
+
+ pj_ansi_snprintf(p, 1500-(p-buf),
+ "%04d-%04d ",
+ i, (i+20 < data_len) ? i+20 : data_len);
+ p += 12;
+
+ for (j=0; j<20 && i<data_len && p<(buf+length-10); ++j, ++i) {
+ pj_ansi_sprintf(p, "%02x ", (*data) & 0xFF);
+ p += 3;
+ data++;
+ }
+
+ pj_ansi_sprintf(p, "\n");
+ p++;
+ }
+
+ return buf;
+}
+
+static int cmp_buf(const pj_uint8_t *s1, const pj_uint8_t *s2, unsigned len)
+{
+ unsigned i;
+ for (i=0; i<len; ++i) {
+ if (s1[i] != s2[i])
+ return i;
+ }
+
+ return -1;
+}
+
+static int fingerprint_test_vector()
+{
+ pj_pool_t *pool;
+ pj_status_t status;
+ unsigned i;
+ int rc = 0;
+
+ PJ_LOG(3,(THIS_FILE, " STUN message test vectors"));
+
+ 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;
+ unsigned parsed_len;
+ unsigned len, 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);
+
+ /* Encode message */
+ if (v->options & USE_MESSAGE_INTEGRITY) {
+ pj_str_t s1, s2;
+
+ pj_stun_create_key(pool, &key, NULL, pj_cstr(&s1, v->username),
+ 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 != -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.username = pj_str(v->username);
+ cred.data.static_cred.data = pj_str(v->password);
+
+ status = pj_stun_authenticate_request(buf, len, msg,
+ &cred, pool, 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 pj_stun_msg* create_msgint1(pj_pool_t *pool, test_vector *v)
+{
+ pj_stun_msg *msg;
+ pj_timestamp u64;
+ pj_str_t s1;
+
+ pj_stun_msg_create(pool, v->msg_type, PJ_STUN_MAGIC,
+ (pj_uint8_t*)v->tsx_id, &msg);
+
+ pj_stun_msg_add_uint_attr(pool, msg, PJ_STUN_ATTR_PRIORITY, 0x6e0001ff);
+ u64.u32.hi = 0x932ff9b1;
+ u64.u32.lo = 0x51263b36;
+ pj_stun_msg_add_uint64_attr(pool, msg, PJ_STUN_ATTR_ICE_CONTROLLED,
+ &u64);
+
+ pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_USERNAME,
+ pj_cstr(&s1, v->username));
+
+ pj_stun_msg_add_msgint_attr(pool, msg);
+
+ pj_stun_msg_add_uint_attr(pool, msg, PJ_STUN_ATTR_FINGERPRINT, 0);
+
+ return msg;
+}
+
+static pj_stun_msg* create_msgint2(pj_pool_t *pool, test_vector *v)
+{
+ pj_stun_msg *msg;
+ pj_sockaddr_in mapped_addr;
+ pj_str_t s1;
+
+ pj_stun_msg_create(pool, v->msg_type, PJ_STUN_MAGIC,
+ (pj_uint8_t*)v->tsx_id, &msg);
+
+ pj_stun_msg_add_string_attr(pool, msg, PJ_STUN_ATTR_SERVER,
+ pj_cstr(&s1, "test vector"));
+
+ pj_sockaddr_in_init(&mapped_addr, pj_cstr(&s1, "127.0.0.1"), 32853);
+ pj_stun_msg_add_sockaddr_attr(pool, msg, PJ_STUN_ATTR_XOR_MAPPED_ADDR,
+ PJ_TRUE, &mapped_addr,
+ sizeof(pj_sockaddr_in));
+
+ pj_stun_msg_add_msgint_attr(pool, msg);
+ pj_stun_msg_add_uint_attr(pool, msg, PJ_STUN_ATTR_FINGERPRINT, 0);
+
+ return msg;
+}
+
int stun_test(void)
{
- decode_verify();
- decode_test();
- auth_test();
- return 0;
+ int pad, rc;
+
+ pad = pj_stun_set_padding_char(32);
+
+ rc = decode_test();
+ if (rc != 0)
+ goto on_return;
+
+ rc = decode_verify();
+ if (rc != 0)
+ goto on_return;
+
+ rc = auth_test();
+ if (rc != 0)
+ goto on_return;
+
+ rc = fingerprint_test_vector();
+ if (rc != 0)
+ goto on_return;
+
+on_return:
+ pj_stun_set_padding_char(pad);
+ return rc;
}
diff --git a/pjnath/src/pjnath-test/test.c b/pjnath/src/pjnath-test/test.c
index b9776539..fc1c124c 100644
--- a/pjnath/src/pjnath-test/test.c
+++ b/pjnath/src/pjnath-test/test.c
@@ -66,6 +66,10 @@ static int test_inner(void)
pjnath_init();
+#if INCLUDE_STUN_TEST
+ DO_TEST(stun_test());
+#endif
+
#if INCLUDE_ICE_TEST
DO_TEST(ice_test());
#endif
diff --git a/pjnath/src/pjnath-test/test.h b/pjnath/src/pjnath-test/test.h
index 5663a84e..39ad4112 100644
--- a/pjnath/src/pjnath-test/test.h
+++ b/pjnath/src/pjnath-test/test.h
@@ -20,8 +20,10 @@
#include <pjlib-util.h>
#include <pjnath.h>
+#define INCLUDE_STUN_TEST 1
#define INCLUDE_ICE_TEST 1
+extern int stun_test(void);
extern int ice_test(void);
extern int test_main(void);