示例#1
0
文件: server.c 项目: kaaustubh/pjsip
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;
}