|
Packit |
3adb1e |
/* ====================================================================
|
|
Packit |
3adb1e |
* Licensed to the Apache Software Foundation (ASF) under one
|
|
Packit |
3adb1e |
* or more contributor license agreements. See the NOTICE file
|
|
Packit |
3adb1e |
* distributed with this work for additional information
|
|
Packit |
3adb1e |
* regarding copyright ownership. The ASF licenses this file
|
|
Packit |
3adb1e |
* to you under the Apache License, Version 2.0 (the
|
|
Packit |
3adb1e |
* "License"); you may not use this file except in compliance
|
|
Packit |
3adb1e |
* with the License. You may obtain a copy of the License at
|
|
Packit |
3adb1e |
*
|
|
Packit |
3adb1e |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
3adb1e |
*
|
|
Packit |
3adb1e |
* Unless required by applicable law or agreed to in writing,
|
|
Packit |
3adb1e |
* software distributed under the License is distributed on an
|
|
Packit |
3adb1e |
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
Packit |
3adb1e |
* KIND, either express or implied. See the License for the
|
|
Packit |
3adb1e |
* specific language governing permissions and limitations
|
|
Packit |
3adb1e |
* under the License.
|
|
Packit |
3adb1e |
* ====================================================================
|
|
Packit |
3adb1e |
*/
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#include <stdlib.h>
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#include <apr.h>
|
|
Packit |
3adb1e |
#include <apr_pools.h>
|
|
Packit |
3adb1e |
#include <apr_strings.h>
|
|
Packit |
3adb1e |
#include <apr_version.h>
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#include "serf.h"
|
|
Packit |
3adb1e |
#include "serf_private.h"
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#include "test_serf.h"
|
|
Packit |
3adb1e |
#include "server/test_server.h"
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate that requests are sent and completed in the order of creation. */
|
|
Packit |
3adb1e |
static void test_serf_connection_request_create(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[2];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
int i;
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "2")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[1], "GET", "/", 2);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that the requests were sent in the order we created them */
|
|
Packit |
3adb1e |
for (i = 0; i < tb->sent_requests->nelts; i++) {
|
|
Packit |
3adb1e |
int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, i + 1, req_nr);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that the requests were received in the order we created them */
|
|
Packit |
3adb1e |
for (i = 0; i < tb->handled_requests->nelts; i++) {
|
|
Packit |
3adb1e |
int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, i + 1, req_nr);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate that priority requests are sent and completed before normal
|
|
Packit |
3adb1e |
requests. */
|
|
Packit |
3adb1e |
static void test_serf_connection_priority_request_create(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[3];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
int i;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "2")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "3")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 2);
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[1], "GET", "/", 3);
|
|
Packit |
3adb1e |
create_new_prio_request(tb, &handler_ctx[2], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that the requests were sent in the order we created them */
|
|
Packit |
3adb1e |
for (i = 0; i < tb->sent_requests->nelts; i++) {
|
|
Packit |
3adb1e |
int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, i + 1, req_nr);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that the requests were received in the order we created them */
|
|
Packit |
3adb1e |
for (i = 0; i < tb->handled_requests->nelts; i++) {
|
|
Packit |
3adb1e |
int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, i + 1, req_nr);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test that serf correctly handles the 'Connection:close' header when the
|
|
Packit |
3adb1e |
server is planning to close the connection. */
|
|
Packit |
3adb1e |
static void test_closed_connection(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[10];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
int done = FALSE, i;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "2")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "3")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "4")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "5")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "6")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "7")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "8")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "9")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(2, "10")}
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND,
|
|
Packit |
3adb1e |
"HTTP/1.1 200 OK" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"Connection: close" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"0" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
},
|
|
Packit |
3adb1e |
{SERVER_IGNORE_AND_KILL_CONNECTION},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND,
|
|
Packit |
3adb1e |
"HTTP/1.1 200 OK" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"Connection: close" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"0" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
},
|
|
Packit |
3adb1e |
{SERVER_IGNORE_AND_KILL_CONNECTION},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server. */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, 12,
|
|
Packit |
3adb1e |
0,
|
|
Packit |
3adb1e |
NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Send some requests on the connections */
|
|
Packit |
3adb1e |
for (i = 0 ; i < num_requests ; i++) {
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[i], "GET", "/", i+1);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
while (1) {
|
|
Packit |
3adb1e |
status = run_test_server(tb->serv_ctx, 0, test_pool);
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_TIMEUP(status))
|
|
Packit |
3adb1e |
status = APR_SUCCESS;
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = serf_context_run(tb->context, 0, test_pool);
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_TIMEUP(status))
|
|
Packit |
3adb1e |
status = APR_SUCCESS;
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Debugging purposes only! */
|
|
Packit |
3adb1e |
serf_debug__closed_conn(tb->bkt_alloc);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
done = TRUE;
|
|
Packit |
3adb1e |
for (i = 0 ; i < num_requests ; i++)
|
|
Packit |
3adb1e |
if (handler_ctx[i].done == FALSE) {
|
|
Packit |
3adb1e |
done = FALSE;
|
|
Packit |
3adb1e |
break;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
if (done)
|
|
Packit |
3adb1e |
break;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that all requests were received */
|
|
Packit |
3adb1e |
CuAssertTrue(tc, tb->sent_requests->nelts >= num_requests);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, num_requests, tb->accepted_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, num_requests, tb->handled_requests->nelts);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test if serf is sending the request to the proxy, not to the server
|
|
Packit |
3adb1e |
directly. */
|
|
Packit |
3adb1e |
static void test_setup_proxy(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
int i;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_pool_t *iter_pool;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{"GET http://localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF\
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF\
|
|
Packit |
3adb1e |
CRLF\
|
|
Packit |
3adb1e |
"1" CRLF\
|
|
Packit |
3adb1e |
"1" CRLF\
|
|
Packit |
3adb1e |
"0" CRLF\
|
|
Packit |
3adb1e |
CRLF}
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list_proxy[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server, no messages expected. */
|
|
Packit |
3adb1e |
status = test_server_proxy_setup(&tb,
|
|
Packit |
3adb1e |
/* server messages and actions */
|
|
Packit |
3adb1e |
NULL, 0,
|
|
Packit |
3adb1e |
NULL, 0,
|
|
Packit |
3adb1e |
/* server messages and actions */
|
|
Packit |
3adb1e |
message_list, 1,
|
|
Packit |
3adb1e |
action_list_proxy, 1,
|
|
Packit |
3adb1e |
0,
|
|
Packit |
3adb1e |
NULL, test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_create(&iter_pool, test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
while (!handler_ctx[0].done)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
apr_pool_clear(iter_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = run_test_server(tb->serv_ctx, 0, iter_pool);
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_TIMEUP(status))
|
|
Packit |
3adb1e |
status = APR_SUCCESS;
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = run_test_server(tb->proxy_ctx, 0, iter_pool);
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_TIMEUP(status))
|
|
Packit |
3adb1e |
status = APR_SUCCESS;
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = serf_context_run(tb->context, 0, iter_pool);
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_TIMEUP(status))
|
|
Packit |
3adb1e |
status = APR_SUCCESS;
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Debugging purposes only! */
|
|
Packit |
3adb1e |
serf_debug__closed_conn(tb->bkt_alloc);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
apr_pool_destroy(iter_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that all requests were received */
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, num_requests, tb->sent_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, num_requests, tb->accepted_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, num_requests, tb->handled_requests->nelts);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that the requests were sent in the order we created them */
|
|
Packit |
3adb1e |
for (i = 0; i < tb->sent_requests->nelts; i++) {
|
|
Packit |
3adb1e |
int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, i + 1, req_nr);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that the requests were received in the order we created them */
|
|
Packit |
3adb1e |
for (i = 0; i < tb->handled_requests->nelts; i++) {
|
|
Packit |
3adb1e |
int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, i + 1, req_nr);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/*****************************************************************************
|
|
Packit |
3adb1e |
* Test if we can make serf send requests one by one.
|
|
Packit |
3adb1e |
*****************************************************************************/
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Resend the first request 4 times by reducing the pipeline bandwidth to
|
|
Packit |
3adb1e |
one request at a time, and by adding the first request again at the start of
|
|
Packit |
3adb1e |
the outgoing queue. */
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
handle_response_keepalive_limit(serf_request_t *request,
|
|
Packit |
3adb1e |
serf_bucket_t *response,
|
|
Packit |
3adb1e |
void *handler_baton,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
handler_baton_t *ctx = handler_baton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (! response) {
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
while (1) {
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
const char *data;
|
|
Packit |
3adb1e |
apr_size_t len;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = serf_bucket_read(response, 2048, &data, &len;;
|
|
Packit |
3adb1e |
if (SERF_BUCKET_READ_ERROR(status)) {
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_EOF(status)) {
|
|
Packit |
3adb1e |
APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id;
|
|
Packit |
3adb1e |
ctx->done = TRUE;
|
|
Packit |
3adb1e |
if (ctx->req_id == 1 && ctx->handled_requests->nelts < 3) {
|
|
Packit |
3adb1e |
serf_connection_priority_request_create(ctx->tb->connection,
|
|
Packit |
3adb1e |
setup_request,
|
|
Packit |
3adb1e |
ctx);
|
|
Packit |
3adb1e |
ctx->done = FALSE;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
return APR_EOF;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#define SEND_REQUESTS 5
|
|
Packit |
3adb1e |
#define RCVD_REQUESTS 7
|
|
Packit |
3adb1e |
static void test_keepalive_limit_one_by_one(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[SEND_REQUESTS];
|
|
Packit |
3adb1e |
int done = FALSE, i;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "2")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "3")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "4")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "5")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server. */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, RCVD_REQUESTS,
|
|
Packit |
3adb1e |
action_list, RCVD_REQUESTS, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
for (i = 0 ; i < SEND_REQUESTS ; i++) {
|
|
Packit |
3adb1e |
create_new_request_with_resp_hdlr(tb, &handler_ctx[i], "GET", "/", i+1,
|
|
Packit |
3adb1e |
handle_response_keepalive_limit);
|
|
Packit |
3adb1e |
/* TODO: don't think this needs to be done in the loop. */
|
|
Packit |
3adb1e |
serf_connection_set_max_outstanding_requests(tb->connection, 1);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
while (1) {
|
|
Packit |
3adb1e |
status = run_test_server(tb->serv_ctx, 0, test_pool);
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_TIMEUP(status))
|
|
Packit |
3adb1e |
status = APR_SUCCESS;
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = serf_context_run(tb->context, 0, test_pool);
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_TIMEUP(status))
|
|
Packit |
3adb1e |
status = APR_SUCCESS;
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Debugging purposes only! */
|
|
Packit |
3adb1e |
serf_debug__closed_conn(tb->bkt_alloc);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
done = TRUE;
|
|
Packit |
3adb1e |
for (i = 0 ; i < SEND_REQUESTS ; i++)
|
|
Packit |
3adb1e |
if (handler_ctx[i].done == FALSE) {
|
|
Packit |
3adb1e |
done = FALSE;
|
|
Packit |
3adb1e |
break;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
if (done)
|
|
Packit |
3adb1e |
break;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that all requests were received */
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, RCVD_REQUESTS, tb->sent_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, RCVD_REQUESTS, tb->accepted_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, RCVD_REQUESTS, tb->handled_requests->nelts);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
#undef SEND_REQUESTS
|
|
Packit |
3adb1e |
#undef RCVD_REQUESTS
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/*****************************************************************************
|
|
Packit |
3adb1e |
* Test if we can make serf first send requests one by one, and then change
|
|
Packit |
3adb1e |
* back to burst mode.
|
|
Packit |
3adb1e |
*****************************************************************************/
|
|
Packit |
3adb1e |
#define SEND_REQUESTS 5
|
|
Packit |
3adb1e |
#define RCVD_REQUESTS 7
|
|
Packit |
3adb1e |
/* Resend the first request 2 times by reducing the pipeline bandwidth to
|
|
Packit |
3adb1e |
one request at a time, and by adding the first request again at the start of
|
|
Packit |
3adb1e |
the outgoing queue. */
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
handle_response_keepalive_limit_burst(serf_request_t *request,
|
|
Packit |
3adb1e |
serf_bucket_t *response,
|
|
Packit |
3adb1e |
void *handler_baton,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
handler_baton_t *ctx = handler_baton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (! response) {
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
while (1) {
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
const char *data;
|
|
Packit |
3adb1e |
apr_size_t len;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = serf_bucket_read(response, 2048, &data, &len;;
|
|
Packit |
3adb1e |
if (SERF_BUCKET_READ_ERROR(status)) {
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_EOF(status)) {
|
|
Packit |
3adb1e |
APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id;
|
|
Packit |
3adb1e |
ctx->done = TRUE;
|
|
Packit |
3adb1e |
if (ctx->req_id == 1 && ctx->handled_requests->nelts < 3) {
|
|
Packit |
3adb1e |
serf_connection_priority_request_create(ctx->tb->connection,
|
|
Packit |
3adb1e |
setup_request,
|
|
Packit |
3adb1e |
ctx);
|
|
Packit |
3adb1e |
ctx->done = FALSE;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
else {
|
|
Packit |
3adb1e |
/* No more one-by-one. */
|
|
Packit |
3adb1e |
serf_connection_set_max_outstanding_requests(ctx->tb->connection,
|
|
Packit |
3adb1e |
0);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
return APR_EOF;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_EAGAIN(status)) {
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_keepalive_limit_one_by_one_and_burst(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[SEND_REQUESTS];
|
|
Packit |
3adb1e |
int done = FALSE, i;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "2")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "3")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "4")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "5")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server. */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, RCVD_REQUESTS,
|
|
Packit |
3adb1e |
action_list, RCVD_REQUESTS, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
for (i = 0 ; i < SEND_REQUESTS ; i++) {
|
|
Packit |
3adb1e |
create_new_request_with_resp_hdlr(tb, &handler_ctx[i], "GET", "/", i+1,
|
|
Packit |
3adb1e |
handle_response_keepalive_limit_burst);
|
|
Packit |
3adb1e |
serf_connection_set_max_outstanding_requests(tb->connection, 1);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
while (1) {
|
|
Packit |
3adb1e |
status = run_test_server(tb->serv_ctx, 0, test_pool);
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_TIMEUP(status))
|
|
Packit |
3adb1e |
status = APR_SUCCESS;
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = serf_context_run(tb->context, 0, test_pool);
|
|
Packit |
3adb1e |
if (APR_STATUS_IS_TIMEUP(status))
|
|
Packit |
3adb1e |
status = APR_SUCCESS;
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Debugging purposes only! */
|
|
Packit |
3adb1e |
serf_debug__closed_conn(tb->bkt_alloc);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
done = TRUE;
|
|
Packit |
3adb1e |
for (i = 0 ; i < SEND_REQUESTS ; i++)
|
|
Packit |
3adb1e |
if (handler_ctx[i].done == FALSE) {
|
|
Packit |
3adb1e |
done = FALSE;
|
|
Packit |
3adb1e |
break;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
if (done)
|
|
Packit |
3adb1e |
break;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that all requests were received */
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, RCVD_REQUESTS, tb->sent_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, RCVD_REQUESTS, tb->accepted_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, RCVD_REQUESTS, tb->handled_requests->nelts);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
#undef SEND_REQUESTS
|
|
Packit |
3adb1e |
#undef RCVD_REQUESTS
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
typedef struct {
|
|
Packit |
3adb1e |
apr_off_t read;
|
|
Packit |
3adb1e |
apr_off_t written;
|
|
Packit |
3adb1e |
} progress_baton_t;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void
|
|
Packit |
3adb1e |
progress_cb(void *progress_baton, apr_off_t read, apr_off_t written)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = progress_baton;
|
|
Packit |
3adb1e |
progress_baton_t *pb = tb->user_baton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
pb->read = read;
|
|
Packit |
3adb1e |
pb->written = written;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t progress_conn_setup(apr_socket_t *skt,
|
|
Packit |
3adb1e |
serf_bucket_t **input_bkt,
|
|
Packit |
3adb1e |
serf_bucket_t **output_bkt,
|
|
Packit |
3adb1e |
void *setup_baton,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = setup_baton;
|
|
Packit |
3adb1e |
*input_bkt = serf_context_bucket_socket_create(tb->context, skt, tb->bkt_alloc);
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_progress_callback(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[5];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
int i;
|
|
Packit |
3adb1e |
progress_baton_t *pb;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "2")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "3")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "4")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "5")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_RESPONSE(1, "2")},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server. */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
progress_conn_setup, test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up the progress callback. */
|
|
Packit |
3adb1e |
pb = apr_pcalloc(test_pool, sizeof(*pb));
|
|
Packit |
3adb1e |
tb->user_baton = pb;
|
|
Packit |
3adb1e |
serf_context_set_progress_cb(tb->context, progress_cb, tb);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Send some requests on the connections */
|
|
Packit |
3adb1e |
for (i = 0 ; i < num_requests ; i++) {
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[i], "GET", "/", i+1);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that progress was reported. */
|
|
Packit |
3adb1e |
CuAssertTrue(tc, pb->written > 0);
|
|
Packit |
3adb1e |
CuAssertTrue(tc, pb->read > 0);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test that username:password components in url are ignored. */
|
|
Packit |
3adb1e |
static void test_connection_userinfo_in_url(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[2];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
int i;
|
|
Packit |
3adb1e |
progress_baton_t *pb;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "2")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_RESPONSE(1, "2")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server. */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
progress_conn_setup, test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Create a connection using user:password@hostname syntax */
|
|
Packit |
3adb1e |
tb->serv_url = "http://user:password@localhost:" SERV_PORT_STR;
|
|
Packit |
3adb1e |
use_new_connection(tb, test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Send some requests on the connections */
|
|
Packit |
3adb1e |
for (i = 0 ; i < num_requests ; i++) {
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[i], "GET", "/", i+1);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/*****************************************************************************
|
|
Packit |
3adb1e |
* Issue #91: test that serf correctly handle an incoming 4xx reponse while
|
|
Packit |
3adb1e |
* the outgoing request wasn't written completely yet.
|
|
Packit |
3adb1e |
*****************************************************************************/
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#define REQUEST_PART1 "PROPFIND / HTTP/1.1" CRLF\
|
|
Packit |
3adb1e |
"Host: lgo-ubuntu.local" CRLF\
|
|
Packit |
3adb1e |
"User-Agent: SVN/1.8.0-dev (x86_64-apple-darwin11.4.2) serf/2.0.0" CRLF\
|
|
Packit |
3adb1e |
"Content-Type: text/xml" CRLF\
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF \
|
|
Packit |
3adb1e |
CRLF\
|
|
Packit |
3adb1e |
"12d" CRLF\
|
|
Packit |
3adb1e |
"<propfind xmlns=""DAV:""><prop>"
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#define REQUEST_PART2 \
|
|
Packit |
3adb1e |
"<resourcetype xmlns=""DAV:""/><getcontentlength xmlns=""DAV:""/>"\
|
|
Packit |
3adb1e |
"<deadprop-count xmlns=""http://subversion.tigris.org/xmlns/dav/""/>"\
|
|
Packit |
3adb1e |
"<version-name xmlns=""DAV:""/><creationdate xmlns=""DAV:""/>"\
|
|
Packit |
3adb1e |
"<creator-displayname xmlns=""DAV:""/></prop></propfind>" CRLF\
|
|
Packit |
3adb1e |
"0" CRLF \
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#define RESPONSE_408 "HTTP/1.1 408 Request Time-out" CRLF\
|
|
Packit |
3adb1e |
"Date: Wed, 14 Nov 2012 19:50:35 GMT" CRLF\
|
|
Packit |
3adb1e |
"Server: Apache/2.2.17 (Ubuntu)" CRLF\
|
|
Packit |
3adb1e |
"Vary: Accept-Encoding" CRLF\
|
|
Packit |
3adb1e |
"Content-Length: 305" CRLF\
|
|
Packit |
3adb1e |
"Connection: close" CRLF\
|
|
Packit |
3adb1e |
"Content-Type: text/html; charset=iso-8859-1" CRLF \
|
|
Packit |
3adb1e |
CRLF\
|
|
Packit |
3adb1e |
"<html><head>"\
|
|
Packit |
3adb1e |
"<title>408 Request Time-out</title></head><body>Request Time-out"\
|
|
Packit |
3adb1e |
"Server timeout waiting for the HTTP request from the client. "\
|
|
Packit |
3adb1e |
"<address>Apache/2.2.17 (Ubuntu) Server at lgo-ubuntu.local Port 80</address>"\
|
|
Packit |
3adb1e |
"</body></html>"
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
serf_bucket_t *body_bkt;
|
|
Packit |
3adb1e |
handler_baton_t *ctx = baton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (ctx->done) {
|
|
Packit |
3adb1e |
body_bkt = serf_bucket_simple_create(REQUEST_PART1, strlen(REQUEST_PART2),
|
|
Packit |
3adb1e |
NULL, NULL,
|
|
Packit |
3adb1e |
ctx->tb->bkt_alloc);
|
|
Packit |
3adb1e |
serf_bucket_aggregate_append(aggregate_bucket, body_bkt);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_EAGAIN;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t setup_request_timeout(
|
|
Packit |
3adb1e |
serf_request_t *request,
|
|
Packit |
3adb1e |
void *setup_baton,
|
|
Packit |
3adb1e |
serf_bucket_t **req_bkt,
|
|
Packit |
3adb1e |
serf_response_acceptor_t *acceptor,
|
|
Packit |
3adb1e |
void **acceptor_baton,
|
|
Packit |
3adb1e |
serf_response_handler_t *handler,
|
|
Packit |
3adb1e |
void **handler_baton,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
handler_baton_t *ctx = setup_baton;
|
|
Packit |
3adb1e |
serf_bucket_t *body_bkt;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
*req_bkt = serf__bucket_stream_create(serf_request_get_alloc(request),
|
|
Packit |
3adb1e |
detect_eof,
|
|
Packit |
3adb1e |
ctx);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* create a simple body text */
|
|
Packit |
3adb1e |
body_bkt = serf_bucket_simple_create(REQUEST_PART1, strlen(REQUEST_PART1),
|
|
Packit |
3adb1e |
NULL, NULL,
|
|
Packit |
3adb1e |
serf_request_get_alloc(request));
|
|
Packit |
3adb1e |
serf_bucket_aggregate_append(*req_bkt, body_bkt);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
APR_ARRAY_PUSH(ctx->sent_requests, int) = ctx->req_id;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
*acceptor = ctx->acceptor;
|
|
Packit |
3adb1e |
*acceptor_baton = ctx;
|
|
Packit |
3adb1e |
*handler = ctx->handler;
|
|
Packit |
3adb1e |
*handler_baton = ctx;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t handle_response_timeout(
|
|
Packit |
3adb1e |
serf_request_t *request,
|
|
Packit |
3adb1e |
serf_bucket_t *response,
|
|
Packit |
3adb1e |
void *handler_baton,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
handler_baton_t *ctx = handler_baton;
|
|
Packit |
3adb1e |
serf_status_line sl;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (! response) {
|
|
Packit |
3adb1e |
serf_connection_request_create(ctx->tb->connection,
|
|
Packit |
3adb1e |
setup_request,
|
|
Packit |
3adb1e |
ctx);
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (serf_request_is_written(request) != APR_EBUSY) {
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = serf_bucket_response_status(response, &sl);
|
|
Packit |
3adb1e |
if (SERF_BUCKET_READ_ERROR(status)) {
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
if (!sl.version && (APR_STATUS_IS_EOF(status) ||
|
|
Packit |
3adb1e |
APR_STATUS_IS_EAGAIN(status))) {
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
if (sl.code == 408) {
|
|
Packit |
3adb1e |
APR_ARRAY_PUSH(ctx->handled_requests, int) = ctx->req_id;
|
|
Packit |
3adb1e |
ctx->done = TRUE;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* discard the rest of the body */
|
|
Packit |
3adb1e |
while (1) {
|
|
Packit |
3adb1e |
const char *data;
|
|
Packit |
3adb1e |
apr_size_t len;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = serf_bucket_read(response, 2048, &data, &len;;
|
|
Packit |
3adb1e |
if (SERF_BUCKET_READ_ERROR(status) ||
|
|
Packit |
3adb1e |
APR_STATUS_IS_EAGAIN(status) ||
|
|
Packit |
3adb1e |
APR_STATUS_IS_EOF(status))
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_request_timeout(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{REQUEST_PART1},
|
|
Packit |
3adb1e |
{REQUEST_PART2},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, RESPONSE_408},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server. */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, 2,
|
|
Packit |
3adb1e |
action_list, 1, 0,
|
|
Packit |
3adb1e |
NULL, test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Send some requests on the connection */
|
|
Packit |
3adb1e |
handler_ctx[0].method = "PROPFIND";
|
|
Packit |
3adb1e |
handler_ctx[0].path = "/";
|
|
Packit |
3adb1e |
handler_ctx[0].done = FALSE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
handler_ctx[0].acceptor = accept_response;
|
|
Packit |
3adb1e |
handler_ctx[0].acceptor_baton = NULL;
|
|
Packit |
3adb1e |
handler_ctx[0].handler = handle_response_timeout;
|
|
Packit |
3adb1e |
handler_ctx[0].req_id = 1;
|
|
Packit |
3adb1e |
handler_ctx[0].accepted_requests = tb->accepted_requests;
|
|
Packit |
3adb1e |
handler_ctx[0].sent_requests = tb->sent_requests;
|
|
Packit |
3adb1e |
handler_ctx[0].handled_requests = tb->handled_requests;
|
|
Packit |
3adb1e |
handler_ctx[0].tb = tb;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf_connection_request_create(tb->connection,
|
|
Packit |
3adb1e |
setup_request_timeout,
|
|
Packit |
3adb1e |
&handler_ctx[0]);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static const char *create_large_response_message(apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
const char *response = "HTTP/1.1 200 OK" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF;
|
|
Packit |
3adb1e |
struct iovec vecs[500];
|
|
Packit |
3adb1e |
const int num_vecs = 500;
|
|
Packit |
3adb1e |
int i, j;
|
|
Packit |
3adb1e |
apr_size_t len;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
vecs[0].iov_base = (char *)response;
|
|
Packit |
3adb1e |
vecs[0].iov_len = strlen(response);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
for (i = 1; i < num_vecs; i++)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
int chunk_len = 10 * i * 3;
|
|
Packit |
3adb1e |
char *chunk;
|
|
Packit |
3adb1e |
char *buf;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* end with empty chunk */
|
|
Packit |
3adb1e |
if (i == num_vecs - 1)
|
|
Packit |
3adb1e |
chunk_len = 0;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
buf = apr_pcalloc(pool, chunk_len + 1);
|
|
Packit |
3adb1e |
for (j = 0; j < chunk_len; j += 10)
|
|
Packit |
3adb1e |
memcpy(buf + j, "0123456789", 10);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
chunk = apr_pstrcat(pool,
|
|
Packit |
3adb1e |
apr_psprintf(pool, "%x", chunk_len),
|
|
Packit |
3adb1e |
CRLF, buf, CRLF, NULL);
|
|
Packit |
3adb1e |
vecs[i].iov_base = chunk;
|
|
Packit |
3adb1e |
vecs[i].iov_len = strlen(chunk);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return apr_pstrcatv(pool, vecs, num_vecs, &len;;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate reading a large chunked response. */
|
|
Packit |
3adb1e |
static void test_connection_large_response(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list[1];
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* create large chunked response message */
|
|
Packit |
3adb1e |
const char *response = create_large_response_message(test_pool);
|
|
Packit |
3adb1e |
action_list[0].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[0].text = response;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static const char *create_large_request_message(apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
const char *request = "GET / HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF;
|
|
Packit |
3adb1e |
struct iovec vecs[500];
|
|
Packit |
3adb1e |
const int num_vecs = 500;
|
|
Packit |
3adb1e |
int i, j;
|
|
Packit |
3adb1e |
apr_size_t len;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
vecs[0].iov_base = (char *)request;
|
|
Packit |
3adb1e |
vecs[0].iov_len = strlen(request);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
for (i = 1; i < num_vecs; i++)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
int chunk_len = 10 * i * 3;
|
|
Packit |
3adb1e |
char *chunk;
|
|
Packit |
3adb1e |
char *buf;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* end with empty chunk */
|
|
Packit |
3adb1e |
if (i == num_vecs - 1)
|
|
Packit |
3adb1e |
chunk_len = 0;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
buf = apr_pcalloc(pool, chunk_len + 1);
|
|
Packit |
3adb1e |
for (j = 0; j < chunk_len; j += 10)
|
|
Packit |
3adb1e |
memcpy(buf + j, "0123456789", 10);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
chunk = apr_pstrcat(pool,
|
|
Packit |
3adb1e |
apr_psprintf(pool, "%x", chunk_len),
|
|
Packit |
3adb1e |
CRLF, buf, CRLF, NULL);
|
|
Packit |
3adb1e |
vecs[i].iov_base = chunk;
|
|
Packit |
3adb1e |
vecs[i].iov_len = strlen(chunk);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return apr_pstrcatv(pool, vecs, num_vecs, &len;;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate sending a large chunked response. */
|
|
Packit |
3adb1e |
static void test_connection_large_request(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
test_server_message_t message_list[1];
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
const char *request;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* create large chunked request message */
|
|
Packit |
3adb1e |
request = create_large_request_message(test_pool);
|
|
Packit |
3adb1e |
message_list[0].text = request;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
handler_ctx[0].request = request;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/*****************************************************************************
|
|
Packit |
3adb1e |
* SSL handshake tests
|
|
Packit |
3adb1e |
*****************************************************************************/
|
|
Packit |
3adb1e |
static const char *server_certs[] = {
|
|
Packit |
3adb1e |
"test/server/serfservercert.pem",
|
|
Packit |
3adb1e |
"test/server/serfcacert.pem",
|
|
Packit |
3adb1e |
NULL };
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static const char *all_server_certs[] = {
|
|
Packit |
3adb1e |
"test/server/serfservercert.pem",
|
|
Packit |
3adb1e |
"test/server/serfcacert.pem",
|
|
Packit |
3adb1e |
"test/server/serfrootcacert.pem",
|
|
Packit |
3adb1e |
NULL };
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static const char **server_certs_srcdir(const char **certs,
|
|
Packit |
3adb1e |
apr_pool_t *result_pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
const char **result;
|
|
Packit |
3adb1e |
int i = 0;
|
|
Packit |
3adb1e |
while (certs[i])
|
|
Packit |
3adb1e |
i++;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
result = apr_pcalloc(result_pool, sizeof(result[0]) * (i + 1));
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
while (i-- > 0)
|
|
Packit |
3adb1e |
result[i] = get_srcdir_file(result_pool, certs[i]);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return result;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t validate_servercert(const serf_ssl_certificate_t *cert,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
apr_hash_t *subject;
|
|
Packit |
3adb1e |
subject = serf_ssl_cert_subject(cert, pool);
|
|
Packit |
3adb1e |
if (strcmp("localhost",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "CN", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Test Suite Server",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "OU", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("In Serf we trust, Inc.",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "O", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Mechelen",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "L", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Antwerp",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "ST", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("BE",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "C", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("serfserver@example.com",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "E", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t validate_cacert(const serf_ssl_certificate_t *cert,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
apr_hash_t *subject;
|
|
Packit |
3adb1e |
subject = serf_ssl_cert_subject(cert, pool);
|
|
Packit |
3adb1e |
if (strcmp("Serf CA",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "CN", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Test Suite CA",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "OU", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("In Serf we trust, Inc.",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "O", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Mechelen",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "L", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Antwerp",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "ST", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("BE",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "C", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("serfca@example.com",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "E", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t validate_rootcacert(const serf_ssl_certificate_t *cert,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
apr_hash_t *subject;
|
|
Packit |
3adb1e |
subject = serf_ssl_cert_subject(cert, pool);
|
|
Packit |
3adb1e |
if (strcmp("Serf Root CA",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "CN", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Test Suite Root CA",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "OU", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("In Serf we trust, Inc.",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "O", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Mechelen",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "L", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Antwerp",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "ST", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("BE",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "C", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("serfrootca@example.com",
|
|
Packit |
3adb1e |
apr_hash_get(subject, "E", APR_HASH_KEY_STRING)) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_failures(void *baton, int failures,
|
|
Packit |
3adb1e |
const serf_ssl_certificate_t *cert)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = baton;
|
|
Packit |
3adb1e |
int expected_failures = *(int *)tb->user_baton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
tb->result_flags |= TEST_RESULT_SERVERCERTCB_CALLED;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* We expect an error from the certificate validation function. */
|
|
Packit |
3adb1e |
if (failures & expected_failures)
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
else
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_allok(void *baton, int failures,
|
|
Packit |
3adb1e |
const serf_ssl_certificate_t *cert)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = baton;
|
|
Packit |
3adb1e |
tb->result_flags |= TEST_RESULT_SERVERCERTCB_CALLED;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* No error expected, certificate is valid. */
|
|
Packit |
3adb1e |
if (failures)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
else
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
ssl_server_cert_cb_reject(void *baton, int failures,
|
|
Packit |
3adb1e |
const serf_ssl_certificate_t *cert)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate that we can connect successfully to an https server. This
|
|
Packit |
3adb1e |
certificate is not trusted, so a cert validation failure is expected. */
|
|
Packit |
3adb1e |
static void test_ssl_handshake(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
int expected_failures;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
static const char *server_cert[] = { "test/server/serfservercert.pem",
|
|
Packit |
3adb1e |
NULL };
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
NULL, /* default conn setup */
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_cert, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_failures,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* This unknown failures is X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE,
|
|
Packit |
3adb1e |
meaning the chain has only the server cert. A good candidate for its
|
|
Packit |
3adb1e |
own failure code. */
|
|
Packit |
3adb1e |
expected_failures = SERF_SSL_CERT_UNKNOWNCA;
|
|
Packit |
3adb1e |
tb->user_baton = &expected_failures;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up the ssl context with the CA and root CA certificates needed for
|
|
Packit |
3adb1e |
successful valiation of the server certificate. */
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup(apr_socket_t *skt,
|
|
Packit |
3adb1e |
serf_bucket_t **input_bkt,
|
|
Packit |
3adb1e |
serf_bucket_t **output_bkt,
|
|
Packit |
3adb1e |
void *setup_baton,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
serf_ssl_certificate_t *rootcacert;
|
|
Packit |
3adb1e |
test_baton_t *tb = setup_baton;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = default_https_conn_setup(skt, input_bkt, output_bkt,
|
|
Packit |
3adb1e |
setup_baton, pool);
|
|
Packit |
3adb1e |
if (status)
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = serf_ssl_load_cert_file(&rootcacert,
|
|
Packit |
3adb1e |
get_srcdir_file(pool,
|
|
Packit |
3adb1e |
"test/server/serfrootcacert.pem"),
|
|
Packit |
3adb1e |
pool);
|
|
Packit |
3adb1e |
if (status)
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
status = serf_ssl_trust_cert(tb->ssl_context, rootcacert);
|
|
Packit |
3adb1e |
if (status)
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate that server certificate validation is ok when we
|
|
Packit |
3adb1e |
explicitly trust our self-signed root ca. */
|
|
Packit |
3adb1e |
static void test_ssl_trust_rootca(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_allok,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate that when the application rejects the cert, the context loop
|
|
Packit |
3adb1e |
bails out with an error. */
|
|
Packit |
3adb1e |
static void test_ssl_application_rejects_cert(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* The certificate is valid, but we tell serf to reject it. */
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
ssl_server_cert_cb_reject,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_helper_run_requests_no_check(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
/* We expect an error from the certificate validation function. */
|
|
Packit |
3adb1e |
CuAssert(tc, "Application told serf the certificate should be rejected,"
|
|
Packit |
3adb1e |
" expected error!", status != APR_SUCCESS);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test for ssl certificate chain callback. */
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
cert_chain_cb(void *baton,
|
|
Packit |
3adb1e |
int failures,
|
|
Packit |
3adb1e |
int error_depth,
|
|
Packit |
3adb1e |
const serf_ssl_certificate_t * const * certs,
|
|
Packit |
3adb1e |
apr_size_t certs_len)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = baton;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
tb->result_flags |= TEST_RESULT_SERVERCERTCHAINCB_CALLED;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (failures)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (certs_len != 3)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = validate_rootcacert(certs[2], tb->pool);
|
|
Packit |
3adb1e |
if (status)
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = validate_cacert(certs[1], tb->pool);
|
|
Packit |
3adb1e |
if (status)
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = validate_servercert(certs[0], tb->pool);
|
|
Packit |
3adb1e |
if (status)
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
chain_rootca_callback_conn_setup(apr_socket_t *skt,
|
|
Packit |
3adb1e |
serf_bucket_t **input_bkt,
|
|
Packit |
3adb1e |
serf_bucket_t **output_bkt,
|
|
Packit |
3adb1e |
void *setup_baton,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = setup_baton;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = https_set_root_ca_conn_setup(skt, input_bkt, output_bkt,
|
|
Packit |
3adb1e |
setup_baton, pool);
|
|
Packit |
3adb1e |
if (status)
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf_ssl_server_cert_chain_callback_set(tb->ssl_context,
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_allok,
|
|
Packit |
3adb1e |
cert_chain_cb,
|
|
Packit |
3adb1e |
tb);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Make the server return a partial certificate chain (server cert, CA cert),
|
|
Packit |
3adb1e |
the root CA cert is trusted explicitly in the client. Test the chain
|
|
Packit |
3adb1e |
callback. */
|
|
Packit |
3adb1e |
static void test_ssl_certificate_chain_with_anchor(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
chain_rootca_callback_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_allok,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCB_CALLED);
|
|
Packit |
3adb1e |
CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCHAINCB_CALLED);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
cert_chain_all_certs_cb(void *baton,
|
|
Packit |
3adb1e |
int failures,
|
|
Packit |
3adb1e |
int error_depth,
|
|
Packit |
3adb1e |
const serf_ssl_certificate_t * const * certs,
|
|
Packit |
3adb1e |
apr_size_t certs_len)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
/* Root CA cert is selfsigned, ignore this 'failure'. */
|
|
Packit |
3adb1e |
failures &= ~SERF_SSL_CERT_SELF_SIGNED;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return cert_chain_cb(baton, failures, error_depth, certs, certs_len);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
chain_callback_conn_setup(apr_socket_t *skt,
|
|
Packit |
3adb1e |
serf_bucket_t **input_bkt,
|
|
Packit |
3adb1e |
serf_bucket_t **output_bkt,
|
|
Packit |
3adb1e |
void *setup_baton,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = setup_baton;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = default_https_conn_setup(skt, input_bkt, output_bkt,
|
|
Packit |
3adb1e |
setup_baton, pool);
|
|
Packit |
3adb1e |
if (status)
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf_ssl_server_cert_chain_callback_set(tb->ssl_context,
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_allok,
|
|
Packit |
3adb1e |
cert_chain_all_certs_cb,
|
|
Packit |
3adb1e |
tb);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Make the server return the complete certificate chain (server cert, CA cert
|
|
Packit |
3adb1e |
and root CA cert). Test the chain callback. */
|
|
Packit |
3adb1e |
static void test_ssl_certificate_chain_all_from_server(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
chain_callback_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(all_server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_allok,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCB_CALLED);
|
|
Packit |
3adb1e |
CuAssertTrue(tc, tb->result_flags & TEST_RESULT_SERVERCERTCHAINCB_CALLED);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate that the ssl handshake succeeds if no application callbacks
|
|
Packit |
3adb1e |
are set, and the ssl server certificate chains is ok. */
|
|
Packit |
3adb1e |
static void test_ssl_no_servercert_callback_allok(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
NULL, /* No server cert callback */
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate that the ssl handshake fails if no application callbacks
|
|
Packit |
3adb1e |
are set, and the ssl server certificate chains is NOT ok. */
|
|
Packit |
3adb1e |
static void test_ssl_no_servercert_callback_fail(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
NULL, /* default conn setup, no certs */
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
NULL, /* No server cert callback */
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_helper_run_requests_no_check(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
/* We expect an error from the certificate validation function. */
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, SERF_ERROR_SSL_CERT_FAILED, status);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Similar to test_connection_large_response, validate reading a large
|
|
Packit |
3adb1e |
chunked response over SSL. */
|
|
Packit |
3adb1e |
static void test_ssl_large_response(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list[1];
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
const char *response;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
NULL, /* No server cert callback */
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* create large chunked response message */
|
|
Packit |
3adb1e |
response = create_large_response_message(test_pool);
|
|
Packit |
3adb1e |
action_list[0].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[0].text = response;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Similar to test_connection_large_request, validate sending a large
|
|
Packit |
3adb1e |
chunked request over SSL. */
|
|
Packit |
3adb1e |
static void test_ssl_large_request(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
test_server_message_t message_list[1];
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
const char *request;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
NULL, /* No server cert callback */
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* create large chunked request message */
|
|
Packit |
3adb1e |
request = create_large_request_message(test_pool);
|
|
Packit |
3adb1e |
message_list[0].text = request;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
handler_ctx[0].request = request;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t client_cert_cb(void *data, const char **cert_path)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = data;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
tb->result_flags |= TEST_RESULT_CLIENT_CERTCB_CALLED;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
*cert_path = get_srcdir_file(tb->pool, "test/server/serfclientcert.p12");
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t client_cert_pw_cb(void *data,
|
|
Packit |
3adb1e |
const char *cert_path,
|
|
Packit |
3adb1e |
const char **password)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = data;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
tb->result_flags |= TEST_RESULT_CLIENT_CERTPWCB_CALLED;
|
|
Packit |
3adb1e |
if (strcmp(cert_path,
|
|
Packit |
3adb1e |
get_srcdir_file(tb->pool, "test/server/serfclientcert.p12")) == 0)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
*password = "serftest";
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
client_cert_conn_setup(apr_socket_t *skt,
|
|
Packit |
3adb1e |
serf_bucket_t **input_bkt,
|
|
Packit |
3adb1e |
serf_bucket_t **output_bkt,
|
|
Packit |
3adb1e |
void *setup_baton,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb = setup_baton;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = https_set_root_ca_conn_setup(skt, input_bkt, output_bkt,
|
|
Packit |
3adb1e |
setup_baton, pool);
|
|
Packit |
3adb1e |
if (status)
|
|
Packit |
3adb1e |
return status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf_ssl_client_cert_provider_set(tb->ssl_context,
|
|
Packit |
3adb1e |
client_cert_cb,
|
|
Packit |
3adb1e |
tb,
|
|
Packit |
3adb1e |
pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf_ssl_client_cert_password_set(tb->ssl_context,
|
|
Packit |
3adb1e |
client_cert_pw_cb,
|
|
Packit |
3adb1e |
tb,
|
|
Packit |
3adb1e |
pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_ssl_client_certificate(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* The SSL server the complete certificate chain to validate the client
|
|
Packit |
3adb1e |
certificate. */
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
client_cert_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(all_server_certs, test_pool),
|
|
Packit |
3adb1e |
"Serf Client",
|
|
Packit |
3adb1e |
NULL, /* No server cert callback */
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertTrue(tc, tb->result_flags & TEST_RESULT_CLIENT_CERTCB_CALLED);
|
|
Packit |
3adb1e |
CuAssertTrue(tc, tb->result_flags & TEST_RESULT_CLIENT_CERTPWCB_CALLED);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate that the expired certificate is reported as failure in the
|
|
Packit |
3adb1e |
callback. */
|
|
Packit |
3adb1e |
static void test_ssl_expired_server_cert(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
int expected_failures;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
static const char *expired_server_certs[] = {
|
|
Packit |
3adb1e |
"test/server/serfserver_expired_cert.pem",
|
|
Packit |
3adb1e |
"test/server/serfcacert.pem",
|
|
Packit |
3adb1e |
"test/server/serfrootcacert.pem",
|
|
Packit |
3adb1e |
NULL };
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
NULL, /* default conn setup */
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(expired_server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_failures,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
expected_failures = SERF_SSL_CERT_SELF_SIGNED |
|
|
Packit |
3adb1e |
SERF_SSL_CERT_EXPIRED;
|
|
Packit |
3adb1e |
tb->user_baton = &expected_failures;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Validate that the expired certificate is reported as failure in the
|
|
Packit |
3adb1e |
callback. */
|
|
Packit |
3adb1e |
static void test_ssl_future_server_cert(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
int expected_failures;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
static const char *future_server_certs[] = {
|
|
Packit |
3adb1e |
"test/server/serfserver_future_cert.pem",
|
|
Packit |
3adb1e |
"test/server/serfcacert.pem",
|
|
Packit |
3adb1e |
"test/server/serfrootcacert.pem",
|
|
Packit |
3adb1e |
NULL };
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_https_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, num_requests,
|
|
Packit |
3adb1e |
action_list, num_requests, 0,
|
|
Packit |
3adb1e |
NULL, /* default conn setup */
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(future_server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
ssl_server_cert_cb_expect_failures,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
expected_failures = SERF_SSL_CERT_SELF_SIGNED |
|
|
Packit |
3adb1e |
SERF_SSL_CERT_NOTYETVALID;
|
|
Packit |
3adb1e |
tb->user_baton = &expected_failures;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests, handler_ctx,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test if serf is sets up an SSL tunnel to the proxy and doesn't contact the
|
|
Packit |
3adb1e |
https server directly. */
|
|
Packit |
3adb1e |
static void test_setup_ssltunnel(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
int i;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* TODO: issue 83: should be relative uri instead of absolute. */
|
|
Packit |
3adb1e |
test_server_message_t message_list_server[] = {
|
|
Packit |
3adb1e |
{"GET / HTTP/1.1" CRLF\
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF\
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF\
|
|
Packit |
3adb1e |
CRLF\
|
|
Packit |
3adb1e |
"1" CRLF\
|
|
Packit |
3adb1e |
"1" CRLF\
|
|
Packit |
3adb1e |
"0" CRLF\
|
|
Packit |
3adb1e |
CRLF}
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list_server[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_message_t message_list_proxy[] = {
|
|
Packit |
3adb1e |
{"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF\
|
|
Packit |
3adb1e |
CRLF },
|
|
Packit |
3adb1e |
{ NULL }
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list_proxy[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
/* Forward the remainder of the data to the server without validation */
|
|
Packit |
3adb1e |
{PROXY_FORWARD, "https://localhost:" SERV_PORT_STR},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server and a proxy. Serf should send a
|
|
Packit |
3adb1e |
CONNECT request to the server. */
|
|
Packit |
3adb1e |
status = test_https_server_proxy_setup(&tb,
|
|
Packit |
3adb1e |
/* server messages and actions */
|
|
Packit |
3adb1e |
message_list_server, 1,
|
|
Packit |
3adb1e |
action_list_server, 1,
|
|
Packit |
3adb1e |
/* proxy messages and actions */
|
|
Packit |
3adb1e |
message_list_proxy, 2,
|
|
Packit |
3adb1e |
action_list_proxy, 2,
|
|
Packit |
3adb1e |
0,
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
NULL, /* No server cert callback */
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that the requests were sent in the order we created them */
|
|
Packit |
3adb1e |
for (i = 0; i < tb->sent_requests->nelts; i++) {
|
|
Packit |
3adb1e |
int req_nr = APR_ARRAY_IDX(tb->sent_requests, i, int);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, i + 1, req_nr);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Check that the requests were received in the order we created them */
|
|
Packit |
3adb1e |
for (i = 0; i < tb->handled_requests->nelts; i++) {
|
|
Packit |
3adb1e |
int req_nr = APR_ARRAY_IDX(tb->handled_requests, i, int);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, i + 1, req_nr);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test error if no creds callback */
|
|
Packit |
3adb1e |
static void test_ssltunnel_no_creds_cb(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list_proxy[] = {
|
|
Packit |
3adb1e |
{"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF\
|
|
Packit |
3adb1e |
CRLF },
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list_proxy[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, "HTTP/1.1 407 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server and a proxy. Serf should send a
|
|
Packit |
3adb1e |
CONNECT request to the server. */
|
|
Packit |
3adb1e |
status = test_https_server_proxy_setup(&tb,
|
|
Packit |
3adb1e |
/* server messages and actions */
|
|
Packit |
3adb1e |
NULL, 0,
|
|
Packit |
3adb1e |
NULL, 0,
|
|
Packit |
3adb1e |
/* proxy messages and actions */
|
|
Packit |
3adb1e |
message_list_proxy, 1,
|
|
Packit |
3adb1e |
action_list_proxy, 1,
|
|
Packit |
3adb1e |
0,
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
NULL, /* No server cert callback */
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* No credentials callback configured. */
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_helper_run_requests_no_check(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, SERF_ERROR_SSLTUNNEL_SETUP_FAILED, status);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
ssltunnel_basic_authn_callback(char **username,
|
|
Packit |
3adb1e |
char **password,
|
|
Packit |
3adb1e |
serf_request_t *request, void *baton,
|
|
Packit |
3adb1e |
int code, const char *authn_type,
|
|
Packit |
3adb1e |
const char *realm,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
handler_baton_t *handler_ctx = baton;
|
|
Packit |
3adb1e |
test_baton_t *tb = handler_ctx->tb;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf__log(TEST_VERBOSE, __FILE__, "ssltunnel_basic_authn_callback\n");
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (strcmp("Basic", authn_type) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (code == 401) {
|
|
Packit |
3adb1e |
if (strcmp("<https://localhost:12345> Test Suite", realm) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
*username = "serf";
|
|
Packit |
3adb1e |
*password = "serftest";
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
else if (code == 407) {
|
|
Packit |
3adb1e |
if (strcmp("<http://localhost:23456> Test Suite Proxy", realm) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
*username = "serfproxy";
|
|
Packit |
3adb1e |
*password = "serftest";
|
|
Packit |
3adb1e |
} else
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf__log(TEST_VERBOSE, __FILE__, "ssltunnel_basic_authn_callback finished successfully.\n");
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test if serf can successfully authenticate to a proxy used for an ssl
|
|
Packit |
3adb1e |
tunnel. Retry the authentication a few times to test requeueing of the
|
|
Packit |
3adb1e |
CONNECT request. */
|
|
Packit |
3adb1e |
static void ssltunnel_basic_auth(CuTest *tc, const char *server_resp_hdrs,
|
|
Packit |
3adb1e |
const char *proxy_407_resp_hdrs,
|
|
Packit |
3adb1e |
const char *proxy_200_resp_hdrs)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
int num_requests_sent, num_requests_recvd;
|
|
Packit |
3adb1e |
test_server_message_t message_list_server[2];
|
|
Packit |
3adb1e |
test_server_action_t action_list_proxy[7];
|
|
Packit |
3adb1e |
test_server_action_t action_list_server[2];
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list_proxy[] = {
|
|
Packit |
3adb1e |
{"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF
|
|
Packit |
3adb1e |
CRLF },
|
|
Packit |
3adb1e |
{"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF
|
|
Packit |
3adb1e |
"Proxy-Authorization: Basic c2VyZnByb3h5OnNlcmZ0ZXN0" CRLF
|
|
Packit |
3adb1e |
CRLF },
|
|
Packit |
3adb1e |
{"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF
|
|
Packit |
3adb1e |
"Proxy-Authorization: Basic c2VyZnByb3h5OnNlcmZ0ZXN0" CRLF
|
|
Packit |
3adb1e |
CRLF },
|
|
Packit |
3adb1e |
{"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF
|
|
Packit |
3adb1e |
"Proxy-Authorization: Basic c2VyZnByb3h5OnNlcmZ0ZXN0" CRLF
|
|
Packit |
3adb1e |
CRLF },
|
|
Packit |
3adb1e |
{"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF
|
|
Packit |
3adb1e |
"Proxy-Authorization: Basic c2VyZnByb3h5OnNlcmZ0ZXN0" CRLF
|
|
Packit |
3adb1e |
CRLF },
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
action_list_proxy[0].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list_proxy[0].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"HTTP/1.1 407 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
|
|
Packit |
3adb1e |
"%s"
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, proxy_407_resp_hdrs);
|
|
Packit |
3adb1e |
action_list_proxy[1].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list_proxy[1].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"HTTP/1.1 407 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
|
|
Packit |
3adb1e |
"%s"
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, proxy_407_resp_hdrs);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
action_list_proxy[2].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list_proxy[2].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"HTTP/1.1 407 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"Proxy-Authenticate: Basic realm=""Test Suite Proxy""" CRLF
|
|
Packit |
3adb1e |
"%s"
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, proxy_407_resp_hdrs);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
action_list_proxy[3].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list_proxy[3].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"HTTP/1.1 200 Connection Established" CRLF
|
|
Packit |
3adb1e |
"%s"
|
|
Packit |
3adb1e |
CRLF, proxy_200_resp_hdrs);
|
|
Packit |
3adb1e |
/* Forward the remainder of the data to the server without validation */
|
|
Packit |
3adb1e |
action_list_proxy[4].kind = PROXY_FORWARD;
|
|
Packit |
3adb1e |
action_list_proxy[4].text = "https://localhost:" SERV_PORT_STR;
|
|
Packit |
3adb1e |
/* If the client or the server closes the connection, stop forwarding.*/
|
|
Packit |
3adb1e |
action_list_proxy[5].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list_proxy[5].text = CHUNKED_EMPTY_RESPONSE;
|
|
Packit |
3adb1e |
/* Again after disconnect. */
|
|
Packit |
3adb1e |
action_list_proxy[6].kind = PROXY_FORWARD;
|
|
Packit |
3adb1e |
action_list_proxy[6].text = "https://localhost:" SERV_PORT_STR;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Make the server also require Basic authentication */
|
|
Packit |
3adb1e |
message_list_server[0].text =
|
|
Packit |
3adb1e |
"GET / HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"0" CRLF
|
|
Packit |
3adb1e |
CRLF;
|
|
Packit |
3adb1e |
message_list_server[1].text =
|
|
Packit |
3adb1e |
"GET / HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF
|
|
Packit |
3adb1e |
"Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"0" CRLF
|
|
Packit |
3adb1e |
CRLF;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
action_list_server[0].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list_server[0].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"HTTP/1.1 401 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"WWW-Authenticate: Basic realm=""Test Suite""" CRLF
|
|
Packit |
3adb1e |
"%s"
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, server_resp_hdrs);
|
|
Packit |
3adb1e |
action_list_server[1].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list_server[1].text = CHUNKED_EMPTY_RESPONSE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server and a proxy. Serf should send a
|
|
Packit |
3adb1e |
CONNECT request to the server. */
|
|
Packit |
3adb1e |
status = test_https_server_proxy_setup(&tb,
|
|
Packit |
3adb1e |
/* server messages and actions */
|
|
Packit |
3adb1e |
message_list_server, 2,
|
|
Packit |
3adb1e |
action_list_server, 2,
|
|
Packit |
3adb1e |
/* proxy messages and actions */
|
|
Packit |
3adb1e |
message_list_proxy, 5,
|
|
Packit |
3adb1e |
action_list_proxy, 7,
|
|
Packit |
3adb1e |
0,
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
NULL, /* No server cert callback */
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf_config_authn_types(tb->context, SERF_AUTHN_BASIC);
|
|
Packit |
3adb1e |
serf_config_credentials_callback(tb->context, ssltunnel_basic_authn_callback);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 1);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test that a request is retried and authentication headers are set
|
|
Packit |
3adb1e |
correctly. */
|
|
Packit |
3adb1e |
num_requests_sent = 1;
|
|
Packit |
3adb1e |
num_requests_recvd = 2;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
status = test_helper_run_requests_no_check(tc, tb, num_requests_sent,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_ssltunnel_basic_auth(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
/* KeepAlive On for both proxy and server */
|
|
Packit |
3adb1e |
ssltunnel_basic_auth(tc, "", "", "");
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_ssltunnel_basic_auth_server_has_keepalive_off(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
/* Add Connection:Close header to server response */
|
|
Packit |
3adb1e |
ssltunnel_basic_auth(tc, "Connection: close" CRLF, "", "");
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_ssltunnel_basic_auth_proxy_has_keepalive_off(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
/* Add Connection:Close header to proxy 407 response */
|
|
Packit |
3adb1e |
ssltunnel_basic_auth(tc, "", "Connection: close" CRLF, "");
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_ssltunnel_basic_auth_proxy_close_conn_on_200resp(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
/* Add Connection:Close header to proxy 200 Conn. Establ. response */
|
|
Packit |
3adb1e |
ssltunnel_basic_auth(tc, "", "", "Connection: close" CRLF);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
proxy_digest_authn_callback(char **username,
|
|
Packit |
3adb1e |
char **password,
|
|
Packit |
3adb1e |
serf_request_t *request, void *baton,
|
|
Packit |
3adb1e |
int code, const char *authn_type,
|
|
Packit |
3adb1e |
const char *realm,
|
|
Packit |
3adb1e |
apr_pool_t *pool)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
handler_baton_t *handler_ctx = baton;
|
|
Packit |
3adb1e |
test_baton_t *tb = handler_ctx->tb;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (code != 407)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Digest", authn_type) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("<http://localhost:23456> Test Suite Proxy", realm) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
*username = "serf";
|
|
Packit |
3adb1e |
*password = "serftest";
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test if serf can successfully authenticate to a proxy used for an ssl
|
|
Packit |
3adb1e |
tunnel. */
|
|
Packit |
3adb1e |
static void test_ssltunnel_digest_auth(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[1];
|
|
Packit |
3adb1e |
const int num_requests = sizeof(handler_ctx)/sizeof(handler_ctx[0]);
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list_server[] = {
|
|
Packit |
3adb1e |
{"GET /test/index.html HTTP/1.1" CRLF\
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF\
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF\
|
|
Packit |
3adb1e |
CRLF\
|
|
Packit |
3adb1e |
"1" CRLF\
|
|
Packit |
3adb1e |
"1" CRLF\
|
|
Packit |
3adb1e |
"0" CRLF\
|
|
Packit |
3adb1e |
CRLF}
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list_server[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#define CONNECT_REQ\
|
|
Packit |
3adb1e |
"CONNECT localhost:" SERV_PORT_STR " HTTP/1.1" CRLF\
|
|
Packit |
3adb1e |
"Host: localhost:" SERV_PORT_STR CRLF
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list_proxy[] = {
|
|
Packit |
3adb1e |
{ CONNECT_REQ CRLF },
|
|
Packit |
3adb1e |
{ CONNECT_REQ
|
|
Packit |
3adb1e |
"Proxy-Authorization: Digest realm=\"Test Suite Proxy\", "
|
|
Packit |
3adb1e |
"username=\"serf\", "
|
|
Packit |
3adb1e |
"nonce=\"ABCDEF1234567890\", uri=\"localhost:" SERV_PORT_STR "\", "
|
|
Packit |
3adb1e |
"response=\"15b1841822273b0fd44d2f6457f64213\", opaque=\"myopaque\", "
|
|
Packit |
3adb1e |
"algorithm=\"MD5\"" CRLF
|
|
Packit |
3adb1e |
CRLF },
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
/* Add a Basic header before Digest header, to test that serf uses the most
|
|
Packit |
3adb1e |
secure authentication scheme first, instead of following the order of
|
|
Packit |
3adb1e |
the headers. */
|
|
Packit |
3adb1e |
/* Use non standard case for Proxy-Authenticate header to test case
|
|
Packit |
3adb1e |
insensitivity for http headers. */
|
|
Packit |
3adb1e |
test_server_action_t action_list_proxy[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, "HTTP/1.1 407 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"Proxy-Authenticate: Basic c2VyZjpzZXJmdGVzdA==" CRLF
|
|
Packit |
3adb1e |
"Proxy-Authenticate: NonExistent blablablabla" CRLF
|
|
Packit |
3adb1e |
"proXy-Authenticate: Digest realm=\"Test Suite Proxy\","
|
|
Packit |
3adb1e |
"nonce=\"ABCDEF1234567890\",opaque=\"myopaque\","
|
|
Packit |
3adb1e |
"algorithm=\"MD5\",qop-options=\"auth\"" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF},
|
|
Packit |
3adb1e |
{SERVER_RESPOND, CHUNKED_EMPTY_RESPONSE},
|
|
Packit |
3adb1e |
/* Forward the remainder of the data to the server without validation */
|
|
Packit |
3adb1e |
{PROXY_FORWARD, "https://localhost:" SERV_PORT_STR},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server and a proxy. Serf should send a
|
|
Packit |
3adb1e |
CONNECT request to the server. */
|
|
Packit |
3adb1e |
status = test_https_server_proxy_setup(&tb,
|
|
Packit |
3adb1e |
/* server messages and actions */
|
|
Packit |
3adb1e |
message_list_server, 1,
|
|
Packit |
3adb1e |
action_list_server, 1,
|
|
Packit |
3adb1e |
/* proxy messages and actions */
|
|
Packit |
3adb1e |
message_list_proxy, 2,
|
|
Packit |
3adb1e |
action_list_proxy, 3,
|
|
Packit |
3adb1e |
0,
|
|
Packit |
3adb1e |
https_set_root_ca_conn_setup,
|
|
Packit |
3adb1e |
get_srcdir_file(test_pool, "test/server/serfserverkey.pem"),
|
|
Packit |
3adb1e |
server_certs_srcdir(server_certs, test_pool),
|
|
Packit |
3adb1e |
NULL, /* no client cert */
|
|
Packit |
3adb1e |
NULL, /* No server cert callback */
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf_config_authn_types(tb->context, SERF_AUTHN_BASIC | SERF_AUTHN_DIGEST);
|
|
Packit |
3adb1e |
serf_config_credentials_callback(tb->context, proxy_digest_authn_callback);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/test/index.html", 1);
|
|
Packit |
3adb1e |
test_helper_run_requests_expect_ok(tc, tb, num_requests,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/*****************************************************************************/
|
|
Packit |
3adb1e |
CuSuite *test_context(void)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
CuSuite *suite = CuSuiteNew();
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuSuiteSetSetupTeardownCallbacks(suite, test_setup, test_teardown);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_serf_connection_request_create);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_serf_connection_priority_request_create);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_closed_connection);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_setup_proxy);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_keepalive_limit_one_by_one);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_keepalive_limit_one_by_one_and_burst);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_progress_callback);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_request_timeout);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_connection_large_response);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_connection_large_request);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_connection_userinfo_in_url);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_handshake);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_trust_rootca);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_application_rejects_cert);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_certificate_chain_with_anchor);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_certificate_chain_all_from_server);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_no_servercert_callback_allok);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_no_servercert_callback_fail);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_large_response);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_large_request);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_client_certificate);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_expired_server_cert);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssl_future_server_cert);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_setup_ssltunnel);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssltunnel_no_creds_cb);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth_server_has_keepalive_off);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth_proxy_has_keepalive_off);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssltunnel_basic_auth_proxy_close_conn_on_200resp);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_ssltunnel_digest_auth);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return suite;
|
|
Packit |
3adb1e |
}
|