|
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 <apr_strings.h>
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
#include "serf.h"
|
|
Packit |
3adb1e |
#include "test_serf.h"
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
authn_callback_expect_not_called(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 |
/* Should not have been called. */
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Tests that authn fails if all authn schemes are disabled. */
|
|
Packit |
3adb1e |
static void test_authentication_disabled(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[2];
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")} };
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, "HTTP/1.1 401 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"WWW-Authenticate: Basic realm=""Test Suite""" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF},
|
|
Packit |
3adb1e |
};
|
|
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, 1,
|
|
Packit |
3adb1e |
action_list, 1, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf_config_authn_types(tb->context, SERF_AUTHN_NONE);
|
|
Packit |
3adb1e |
serf_config_credentials_callback(tb->context,
|
|
Packit |
3adb1e |
authn_callback_expect_not_called);
|
|
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, 1,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, SERF_ERROR_AUTHN_NOT_SUPPORTED, status);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, 1, tb->sent_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, 1, tb->accepted_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, 0, tb->handled_requests->nelts);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED));
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Tests that authn fails if encountered an unsupported scheme. */
|
|
Packit |
3adb1e |
static void test_unsupported_authentication(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[2];
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{CHUNKED_REQUEST(1, "1")} };
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{SERVER_RESPOND, "HTTP/1.1 401 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"WWW-Authenticate: NotExistent realm=""Test Suite""" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF},
|
|
Packit |
3adb1e |
};
|
|
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, 1,
|
|
Packit |
3adb1e |
action_list, 1, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
serf_config_authn_types(tb->context, SERF_AUTHN_ALL);
|
|
Packit |
3adb1e |
serf_config_credentials_callback(tb->context,
|
|
Packit |
3adb1e |
authn_callback_expect_not_called);
|
|
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, 1,
|
|
Packit |
3adb1e |
handler_ctx, test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, SERF_ERROR_AUTHN_NOT_SUPPORTED, status);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, 1, tb->sent_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, 1, tb->accepted_requests->nelts);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, 0, tb->handled_requests->nelts);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED));
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
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 |
tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (code != 401)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("Basic", authn_type) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp("<http://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 |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test template, used for KeepAlive Off and KeepAlive On test */
|
|
Packit |
3adb1e |
static void basic_authentication(CuTest *tc, const char *resp_hdrs)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[2];
|
|
Packit |
3adb1e |
int num_requests_sent, num_requests_recvd;
|
|
Packit |
3adb1e |
test_server_message_t message_list[3];
|
|
Packit |
3adb1e |
test_server_action_t action_list[3];
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Expected string relies on strict order of headers, which is not
|
|
Packit |
3adb1e |
guaranteed. c2VyZjpzZXJmdGVzdA== is base64 encoded serf:serftest . */
|
|
Packit |
3adb1e |
message_list[0].text = CHUNKED_REQUEST(1, "1");
|
|
Packit |
3adb1e |
message_list[1].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"GET / HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" 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 CRLF);
|
|
Packit |
3adb1e |
message_list[2].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"GET / HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" CRLF
|
|
Packit |
3adb1e |
"Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"2" CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
action_list[0].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
/* Use non-standard case WWW-Authenticate header and scheme name to test
|
|
Packit |
3adb1e |
for case insensitive comparisons. */
|
|
Packit |
3adb1e |
action_list[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, resp_hdrs);
|
|
Packit |
3adb1e |
action_list[1].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[1].text = CHUNKED_EMPTY_RESPONSE;
|
|
Packit |
3adb1e |
action_list[2].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[2].text = CHUNKED_EMPTY_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, 3,
|
|
Packit |
3adb1e |
action_list, 3, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
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, 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 |
/* Test that credentials were cached by asserting that the authn callback
|
|
Packit |
3adb1e |
wasn't called again. */
|
|
Packit |
3adb1e |
tb->result_flags = 0;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 2);
|
|
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 |
CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED));
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_basic_authentication(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
basic_authentication(tc, "");
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_basic_authentication_keepalive_off(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
basic_authentication(tc, "Connection: close" CRLF);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
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 != 401)
|
|
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: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 |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test template, used for KeepAlive Off and KeepAlive On test */
|
|
Packit |
3adb1e |
static void digest_authentication(CuTest *tc, const char *resp_hdrs)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[2];
|
|
Packit |
3adb1e |
int num_requests_sent, num_requests_recvd;
|
|
Packit |
3adb1e |
test_server_message_t message_list[2];
|
|
Packit |
3adb1e |
test_server_action_t action_list[2];
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Expected string relies on strict order of headers and attributes of
|
|
Packit |
3adb1e |
Digest, both are not guaranteed.
|
|
Packit |
3adb1e |
6ff0d4cc201513ce970d5c6b25e1043b is encoded as:
|
|
Packit |
3adb1e |
md5hex(md5hex("serf:Test Suite:serftest") & ":" &
|
|
Packit |
3adb1e |
md5hex("ABCDEF1234567890") & ":" &
|
|
Packit |
3adb1e |
md5hex("GET:/test/index.html"))
|
|
Packit |
3adb1e |
*/
|
|
Packit |
3adb1e |
message_list[0].text = CHUNKED_REQUEST_URI("/test/index.html", 1, "1");
|
|
Packit |
3adb1e |
message_list[1].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"GET /test/index.html HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" CRLF
|
|
Packit |
3adb1e |
"Authorization: Digest realm=\"Test Suite\", username=\"serf\", "
|
|
Packit |
3adb1e |
"nonce=\"ABCDEF1234567890\", uri=\"/test/index.html\", "
|
|
Packit |
3adb1e |
"response=\"6ff0d4cc201513ce970d5c6b25e1043b\", opaque=\"myopaque\", "
|
|
Packit |
3adb1e |
"algorithm=\"MD5\"" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF);
|
|
Packit |
3adb1e |
action_list[0].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[0].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"HTTP/1.1 401 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"WWW-Authenticate: Digest realm=\"Test Suite\","
|
|
Packit |
3adb1e |
"nonce=\"ABCDEF1234567890\",opaque=\"myopaque\","
|
|
Packit |
3adb1e |
"algorithm=\"MD5\",qop-options=\"auth\"" CRLF
|
|
Packit |
3adb1e |
"%s"
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, resp_hdrs);
|
|
Packit |
3adb1e |
/* If the resp_hdrs includes "Connection: close", serf will automatically
|
|
Packit |
3adb1e |
reset the connection from the client side, no need to use
|
|
Packit |
3adb1e |
SERVER_KILL_CONNECTION. */
|
|
Packit |
3adb1e |
action_list[1].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[1].text = CHUNKED_EMPTY_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, 2,
|
|
Packit |
3adb1e |
action_list, 2, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
Packit |
3adb1e |
CuAssertIntEquals(tc, APR_SUCCESS, status);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Add both Basic and Digest here, should use Digest only. */
|
|
Packit |
3adb1e |
serf_config_authn_types(tb->context, SERF_AUTHN_BASIC | SERF_AUTHN_DIGEST);
|
|
Packit |
3adb1e |
serf_config_credentials_callback(tb->context, digest_authn_callback);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/test/index.html", 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_digest_authentication(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
digest_authentication(tc, "");
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_digest_authentication_keepalive_off(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
/* Add the Connection: close header to the response with the Digest headers.
|
|
Packit |
3adb1e |
This to test that the Digest headers will be added to the retry of the
|
|
Packit |
3adb1e |
request on the new connection. */
|
|
Packit |
3adb1e |
digest_authentication(tc, "Connection: close" CRLF);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static apr_status_t
|
|
Packit |
3adb1e |
switched_realm_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 |
const char *exp_realm = tb->user_baton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (code != 401)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
if (strcmp(exp_realm, realm) != 0)
|
|
Packit |
3adb1e |
return SERF_ERROR_ISSUE_IN_TESTSUITE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
if (strcmp(realm, "<http://localhost:12345> Test Suite") == 0) {
|
|
Packit |
3adb1e |
*username = "serf";
|
|
Packit |
3adb1e |
*password = "serftest";
|
|
Packit |
3adb1e |
} else {
|
|
Packit |
3adb1e |
*username = "serf_newrealm";
|
|
Packit |
3adb1e |
*password = "serftest";
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return APR_SUCCESS;
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Test template, used for both Basic and Digest switch realms test */
|
|
Packit |
3adb1e |
static void authentication_switch_realms(CuTest *tc,
|
|
Packit |
3adb1e |
const char *scheme,
|
|
Packit |
3adb1e |
const char *authn_attr,
|
|
Packit |
3adb1e |
const char *authz_attr_test_suite,
|
|
Packit |
3adb1e |
const char *authz_attr_wrong_realm,
|
|
Packit |
3adb1e |
const char *authz_attr_new_realm)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[2];
|
|
Packit |
3adb1e |
int num_requests_sent, num_requests_recvd;
|
|
Packit |
3adb1e |
test_server_message_t message_list[5];
|
|
Packit |
3adb1e |
test_server_action_t action_list[5];
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
message_list[0].text = CHUNKED_REQUEST(1, "1");
|
|
Packit |
3adb1e |
message_list[1].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"GET / HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" CRLF
|
|
Packit |
3adb1e |
"Authorization: %s %s" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, scheme, authz_attr_test_suite);
|
|
Packit |
3adb1e |
message_list[2].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"GET / HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" CRLF
|
|
Packit |
3adb1e |
"Authorization: %s %s" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"2" CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, scheme, authz_attr_test_suite);
|
|
Packit |
3adb1e |
/* The client doesn't know that /newrealm/ is in another realm, so it
|
|
Packit |
3adb1e |
reuses the credentials cached on the connection. */
|
|
Packit |
3adb1e |
message_list[3].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"GET /newrealm/index.html HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" CRLF
|
|
Packit |
3adb1e |
"Authorization: %s %s" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"3" CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, scheme, authz_attr_wrong_realm);
|
|
Packit |
3adb1e |
message_list[4].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"GET /newrealm/index.html HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" CRLF
|
|
Packit |
3adb1e |
"Authorization: %s %s" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF
|
|
Packit |
3adb1e |
"3" CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, scheme, authz_attr_new_realm);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
action_list[0].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[0].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"HTTP/1.1 401 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"WWW-Authenticate: %s realm=""Test Suite""%s" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, scheme, authn_attr);
|
|
Packit |
3adb1e |
action_list[1].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[1].text = CHUNKED_EMPTY_RESPONSE;
|
|
Packit |
3adb1e |
action_list[2].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[2].text = CHUNKED_EMPTY_RESPONSE;
|
|
Packit |
3adb1e |
action_list[3].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[3].text = apr_psprintf(test_pool,
|
|
Packit |
3adb1e |
"HTTP/1.1 401 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"Transfer-Encoding: chunked" CRLF
|
|
Packit |
3adb1e |
"WWW-Authenticate: %s realm=""New Realm""%s" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
"1" CRLF CRLF
|
|
Packit |
3adb1e |
"0" CRLF CRLF, scheme, authn_attr);
|
|
Packit |
3adb1e |
action_list[4].kind = SERVER_RESPOND;
|
|
Packit |
3adb1e |
action_list[4].text = CHUNKED_EMPTY_RESPONSE;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Set up a test context with a server */
|
|
Packit |
3adb1e |
status = test_http_server_setup(&tb,
|
|
Packit |
3adb1e |
message_list, 5,
|
|
Packit |
3adb1e |
action_list, 5, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
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,
|
|
Packit |
3adb1e |
switched_realm_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 |
tb->user_baton = "<http://localhost:12345> Test Suite";
|
|
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 |
/* Test that credentials were cached by asserting that the authn callback
|
|
Packit |
3adb1e |
wasn't called again. */
|
|
Packit |
3adb1e |
tb->result_flags = 0;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/", 2);
|
|
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 |
CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED));
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
/* Switch realms. Test that serf asks the application for new
|
|
Packit |
3adb1e |
credentials. */
|
|
Packit |
3adb1e |
tb->result_flags = 0;
|
|
Packit |
3adb1e |
tb->user_baton = "<http://localhost:12345> New Realm";
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "GET", "/newrealm/index.html", 3);
|
|
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 |
CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED);
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_basic_switch_realms(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
authentication_switch_realms(tc, "Basic", "", "c2VyZjpzZXJmdGVzdA==",
|
|
Packit |
3adb1e |
"c2VyZjpzZXJmdGVzdA==",
|
|
Packit |
3adb1e |
"c2VyZl9uZXdyZWFsbTpzZXJmdGVzdA==");
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_digest_switch_realms(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
authentication_switch_realms(tc, "Digest", ",nonce=\"ABCDEF1234567890\","
|
|
Packit |
3adb1e |
"opaque=\"myopaque\", algorithm=\"MD5\",qop-options=\"auth\"",
|
|
Packit |
3adb1e |
/* response hdr attribute for Test Suite realm, uri / */
|
|
Packit |
3adb1e |
"realm=\"Test Suite\", username=\"serf\", nonce=\"ABCDEF1234567890\", "
|
|
Packit |
3adb1e |
"uri=\"/\", response=\"3511a71fec5c02ab1c9212711a8baa58\", "
|
|
Packit |
3adb1e |
"opaque=\"myopaque\", algorithm=\"MD5\"",
|
|
Packit |
3adb1e |
/* response hdr attribute for Test Suite realm, uri /newrealm/index.html */
|
|
Packit |
3adb1e |
"realm=\"Test Suite\", username=\"serf\", nonce=\"ABCDEF1234567890\", "
|
|
Packit |
3adb1e |
"uri=\"/newrealm/index.html\", response=\"c6b673cf44ad16ef379930856b607344\", "
|
|
Packit |
3adb1e |
"opaque=\"myopaque\", algorithm=\"MD5\"",
|
|
Packit |
3adb1e |
/* response hdr attribute for New Realm realm, uri /newrealm/index.html */
|
|
Packit |
3adb1e |
"realm=\"New Realm\", username=\"serf_newrealm\", nonce=\"ABCDEF1234567890\", "
|
|
Packit |
3adb1e |
"uri=\"/newrealm/index.html\", response=\"f93f07d1412e53c421f66741a89198cb\", "
|
|
Packit |
3adb1e |
"opaque=\"myopaque\", algorithm=\"MD5\"");
|
|
Packit |
3adb1e |
}
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
static void test_auth_on_HEAD(CuTest *tc)
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
test_baton_t *tb;
|
|
Packit |
3adb1e |
handler_baton_t handler_ctx[2];
|
|
Packit |
3adb1e |
int num_requests_sent, num_requests_recvd;
|
|
Packit |
3adb1e |
apr_status_t status;
|
|
Packit |
3adb1e |
apr_pool_t *test_pool = tc->testBaton;
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
test_server_message_t message_list[] = {
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
"HEAD / HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
},
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
"HEAD / HTTP/1.1" CRLF
|
|
Packit |
3adb1e |
"Host: localhost:12345" CRLF
|
|
Packit |
3adb1e |
"Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
},
|
|
Packit |
3adb1e |
};
|
|
Packit |
3adb1e |
test_server_action_t action_list[] = {
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
SERVER_RESPOND,
|
|
Packit |
3adb1e |
"HTTP/1.1 401 Unauthorized" CRLF
|
|
Packit |
3adb1e |
"WWW-Authenticate: Basic Realm=""Test Suite""" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
},
|
|
Packit |
3adb1e |
{
|
|
Packit |
3adb1e |
SERVER_RESPOND,
|
|
Packit |
3adb1e |
"HTTP/1.1 200 Ok" CRLF
|
|
Packit |
3adb1e |
"Content-Type: text/html" CRLF
|
|
Packit |
3adb1e |
CRLF
|
|
Packit |
3adb1e |
},
|
|
Packit |
3adb1e |
};
|
|
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, 2, 0, NULL,
|
|
Packit |
3adb1e |
test_pool);
|
|
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, basic_authn_callback);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
create_new_request(tb, &handler_ctx[0], "HEAD", "/", -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 |
/*****************************************************************************/
|
|
Packit |
3adb1e |
CuSuite *test_auth(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_authentication_disabled);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_unsupported_authentication);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_basic_authentication);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_basic_authentication_keepalive_off);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_digest_authentication);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_digest_authentication_keepalive_off);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_basic_switch_realms);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_digest_switch_realms);
|
|
Packit |
3adb1e |
SUITE_ADD_TEST(suite, test_auth_on_HEAD);
|
|
Packit |
3adb1e |
|
|
Packit |
3adb1e |
return suite;
|
|
Packit |
3adb1e |
}
|