Blame test/test_auth.c

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
}