| /* ==================================================================== |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * ==================================================================== |
| */ |
| |
| #include <apr_strings.h> |
| |
| #include "serf.h" |
| #include "test_serf.h" |
| |
| static apr_status_t |
| authn_callback_expect_not_called(char **username, |
| char **password, |
| serf_request_t *request, void *baton, |
| int code, const char *authn_type, |
| const char *realm, |
| apr_pool_t *pool) |
| { |
| handler_baton_t *handler_ctx = baton; |
| test_baton_t *tb = handler_ctx->tb; |
| |
| tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; |
| |
| /* Should not have been called. */ |
| return SERF_ERROR_ISSUE_IN_TESTSUITE; |
| } |
| |
| /* Tests that authn fails if all authn schemes are disabled. */ |
| static void test_authentication_disabled(CuTest *tc) |
| { |
| test_baton_t *tb; |
| handler_baton_t handler_ctx[2]; |
| |
| test_server_message_t message_list[] = { |
| {CHUNKED_REQUEST(1, "1")} }; |
| test_server_action_t action_list[] = { |
| {SERVER_RESPOND, "HTTP/1.1 401 Unauthorized" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| "WWW-Authenticate: Basic realm=""Test Suite""" CRLF |
| CRLF |
| "0" CRLF CRLF}, |
| }; |
| apr_status_t status; |
| |
| apr_pool_t *test_pool = tc->testBaton; |
| |
| /* Set up a test context with a server */ |
| status = test_http_server_setup(&tb, |
| message_list, 1, |
| action_list, 1, 0, NULL, |
| test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| |
| serf_config_authn_types(tb->context, SERF_AUTHN_NONE); |
| serf_config_credentials_callback(tb->context, |
| authn_callback_expect_not_called); |
| |
| create_new_request(tb, &handler_ctx[0], "GET", "/", 1); |
| |
| status = test_helper_run_requests_no_check(tc, tb, 1, |
| handler_ctx, test_pool); |
| CuAssertIntEquals(tc, SERF_ERROR_AUTHN_NOT_SUPPORTED, status); |
| CuAssertIntEquals(tc, 1, tb->sent_requests->nelts); |
| CuAssertIntEquals(tc, 1, tb->accepted_requests->nelts); |
| CuAssertIntEquals(tc, 0, tb->handled_requests->nelts); |
| |
| CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED)); |
| } |
| |
| /* Tests that authn fails if encountered an unsupported scheme. */ |
| static void test_unsupported_authentication(CuTest *tc) |
| { |
| test_baton_t *tb; |
| handler_baton_t handler_ctx[2]; |
| |
| test_server_message_t message_list[] = { |
| {CHUNKED_REQUEST(1, "1")} }; |
| test_server_action_t action_list[] = { |
| {SERVER_RESPOND, "HTTP/1.1 401 Unauthorized" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| "WWW-Authenticate: NotExistent realm=""Test Suite""" CRLF |
| CRLF |
| "0" CRLF CRLF}, |
| }; |
| apr_status_t status; |
| |
| apr_pool_t *test_pool = tc->testBaton; |
| |
| /* Set up a test context with a server */ |
| status = test_http_server_setup(&tb, |
| message_list, 1, |
| action_list, 1, 0, NULL, |
| test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| |
| serf_config_authn_types(tb->context, SERF_AUTHN_ALL); |
| serf_config_credentials_callback(tb->context, |
| authn_callback_expect_not_called); |
| |
| create_new_request(tb, &handler_ctx[0], "GET", "/", 1); |
| |
| status = test_helper_run_requests_no_check(tc, tb, 1, |
| handler_ctx, test_pool); |
| CuAssertIntEquals(tc, SERF_ERROR_AUTHN_NOT_SUPPORTED, status); |
| CuAssertIntEquals(tc, 1, tb->sent_requests->nelts); |
| CuAssertIntEquals(tc, 1, tb->accepted_requests->nelts); |
| CuAssertIntEquals(tc, 0, tb->handled_requests->nelts); |
| |
| CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED)); |
| } |
| |
| static apr_status_t |
| basic_authn_callback(char **username, |
| char **password, |
| serf_request_t *request, void *baton, |
| int code, const char *authn_type, |
| const char *realm, |
| apr_pool_t *pool) |
| { |
| handler_baton_t *handler_ctx = baton; |
| test_baton_t *tb = handler_ctx->tb; |
| |
| tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; |
| |
| if (code != 401) |
| return SERF_ERROR_ISSUE_IN_TESTSUITE; |
| if (strcmp("Basic", authn_type) != 0) |
| return SERF_ERROR_ISSUE_IN_TESTSUITE; |
| if (strcmp("<http://localhost:12345> Test Suite", realm) != 0) |
| return SERF_ERROR_ISSUE_IN_TESTSUITE; |
| |
| *username = "serf"; |
| *password = "serftest"; |
| |
| return APR_SUCCESS; |
| } |
| |
| /* Test template, used for KeepAlive Off and KeepAlive On test */ |
| static void basic_authentication(CuTest *tc, const char *resp_hdrs) |
| { |
| test_baton_t *tb; |
| handler_baton_t handler_ctx[2]; |
| int num_requests_sent, num_requests_recvd; |
| test_server_message_t message_list[3]; |
| test_server_action_t action_list[3]; |
| apr_status_t status; |
| |
| apr_pool_t *test_pool = tc->testBaton; |
| |
| /* Expected string relies on strict order of headers, which is not |
| guaranteed. c2VyZjpzZXJmdGVzdA== is base64 encoded serf:serftest . */ |
| message_list[0].text = CHUNKED_REQUEST(1, "1"); |
| message_list[1].text = apr_psprintf(test_pool, |
| "GET / HTTP/1.1" CRLF |
| "Host: localhost:12345" CRLF |
| "Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| CRLF |
| "1" CRLF |
| "1" CRLF |
| "0" CRLF CRLF); |
| message_list[2].text = apr_psprintf(test_pool, |
| "GET / HTTP/1.1" CRLF |
| "Host: localhost:12345" CRLF |
| "Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| CRLF |
| "1" CRLF |
| "2" CRLF |
| "0" CRLF CRLF); |
| |
| action_list[0].kind = SERVER_RESPOND; |
| /* Use non-standard case WWW-Authenticate header and scheme name to test |
| for case insensitive comparisons. */ |
| action_list[0].text = apr_psprintf(test_pool, |
| "HTTP/1.1 401 Unauthorized" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| "www-Authenticate: bAsIc realm=""Test Suite""" CRLF |
| "%s" |
| CRLF |
| "0" CRLF CRLF, resp_hdrs); |
| action_list[1].kind = SERVER_RESPOND; |
| action_list[1].text = CHUNKED_EMPTY_RESPONSE; |
| action_list[2].kind = SERVER_RESPOND; |
| action_list[2].text = CHUNKED_EMPTY_RESPONSE; |
| |
| /* Set up a test context with a server */ |
| status = test_http_server_setup(&tb, |
| message_list, 3, |
| action_list, 3, 0, NULL, |
| test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| |
| serf_config_authn_types(tb->context, SERF_AUTHN_BASIC); |
| serf_config_credentials_callback(tb->context, basic_authn_callback); |
| |
| create_new_request(tb, &handler_ctx[0], "GET", "/", 1); |
| |
| /* Test that a request is retried and authentication headers are set |
| correctly. */ |
| num_requests_sent = 1; |
| num_requests_recvd = 2; |
| |
| status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, |
| handler_ctx, test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts); |
| CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts); |
| CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts); |
| |
| CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); |
| |
| /* Test that credentials were cached by asserting that the authn callback |
| wasn't called again. */ |
| tb->result_flags = 0; |
| |
| create_new_request(tb, &handler_ctx[0], "GET", "/", 2); |
| status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, |
| handler_ctx, test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED)); |
| } |
| |
| static void test_basic_authentication(CuTest *tc) |
| { |
| basic_authentication(tc, ""); |
| } |
| |
| static void test_basic_authentication_keepalive_off(CuTest *tc) |
| { |
| basic_authentication(tc, "Connection: close" CRLF); |
| } |
| |
| static apr_status_t |
| digest_authn_callback(char **username, |
| char **password, |
| serf_request_t *request, void *baton, |
| int code, const char *authn_type, |
| const char *realm, |
| apr_pool_t *pool) |
| { |
| handler_baton_t *handler_ctx = baton; |
| test_baton_t *tb = handler_ctx->tb; |
| |
| tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; |
| |
| if (code != 401) |
| return SERF_ERROR_ISSUE_IN_TESTSUITE; |
| if (strcmp("Digest", authn_type) != 0) |
| return SERF_ERROR_ISSUE_IN_TESTSUITE; |
| if (strcmp("<http://localhost:12345> Test Suite", realm) != 0) |
| return SERF_ERROR_ISSUE_IN_TESTSUITE; |
| |
| *username = "serf"; |
| *password = "serftest"; |
| |
| return APR_SUCCESS; |
| } |
| |
| /* Test template, used for KeepAlive Off and KeepAlive On test */ |
| static void digest_authentication(CuTest *tc, const char *resp_hdrs) |
| { |
| test_baton_t *tb; |
| handler_baton_t handler_ctx[2]; |
| int num_requests_sent, num_requests_recvd; |
| test_server_message_t message_list[2]; |
| test_server_action_t action_list[2]; |
| apr_pool_t *test_pool = tc->testBaton; |
| apr_status_t status; |
| |
| /* Expected string relies on strict order of headers and attributes of |
| Digest, both are not guaranteed. |
| 6ff0d4cc201513ce970d5c6b25e1043b is encoded as: |
| md5hex(md5hex("serf:Test Suite:serftest") & ":" & |
| md5hex("ABCDEF1234567890") & ":" & |
| md5hex("GET:/test/index.html")) |
| */ |
| message_list[0].text = CHUNKED_REQUEST_URI("/test/index.html", 1, "1"); |
| message_list[1].text = apr_psprintf(test_pool, |
| "GET /test/index.html HTTP/1.1" CRLF |
| "Host: localhost:12345" CRLF |
| "Authorization: Digest realm=\"Test Suite\", username=\"serf\", " |
| "nonce=\"ABCDEF1234567890\", uri=\"/test/index.html\", " |
| "response=\"6ff0d4cc201513ce970d5c6b25e1043b\", opaque=\"myopaque\", " |
| "algorithm=\"MD5\"" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| CRLF |
| "1" CRLF |
| "1" CRLF |
| "0" CRLF CRLF); |
| action_list[0].kind = SERVER_RESPOND; |
| action_list[0].text = apr_psprintf(test_pool, |
| "HTTP/1.1 401 Unauthorized" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| "WWW-Authenticate: Digest realm=\"Test Suite\"," |
| "nonce=\"ABCDEF1234567890\",opaque=\"myopaque\"," |
| "algorithm=\"MD5\",qop-options=\"auth\"" CRLF |
| "%s" |
| CRLF |
| "0" CRLF CRLF, resp_hdrs); |
| /* If the resp_hdrs includes "Connection: close", serf will automatically |
| reset the connection from the client side, no need to use |
| SERVER_KILL_CONNECTION. */ |
| action_list[1].kind = SERVER_RESPOND; |
| action_list[1].text = CHUNKED_EMPTY_RESPONSE; |
| |
| /* Set up a test context with a server */ |
| status = test_http_server_setup(&tb, |
| message_list, 2, |
| action_list, 2, 0, NULL, |
| test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| |
| /* Add both Basic and Digest here, should use Digest only. */ |
| serf_config_authn_types(tb->context, SERF_AUTHN_BASIC | SERF_AUTHN_DIGEST); |
| serf_config_credentials_callback(tb->context, digest_authn_callback); |
| |
| create_new_request(tb, &handler_ctx[0], "GET", "/test/index.html", 1); |
| |
| /* Test that a request is retried and authentication headers are set |
| correctly. */ |
| num_requests_sent = 1; |
| num_requests_recvd = 2; |
| |
| status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, |
| handler_ctx, test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts); |
| CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts); |
| CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts); |
| |
| CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); |
| } |
| |
| static void test_digest_authentication(CuTest *tc) |
| { |
| digest_authentication(tc, ""); |
| } |
| |
| static void test_digest_authentication_keepalive_off(CuTest *tc) |
| { |
| /* Add the Connection: close header to the response with the Digest headers. |
| This to test that the Digest headers will be added to the retry of the |
| request on the new connection. */ |
| digest_authentication(tc, "Connection: close" CRLF); |
| } |
| |
| static apr_status_t |
| switched_realm_authn_callback(char **username, |
| char **password, |
| serf_request_t *request, void *baton, |
| int code, const char *authn_type, |
| const char *realm, |
| apr_pool_t *pool) |
| { |
| handler_baton_t *handler_ctx = baton; |
| test_baton_t *tb = handler_ctx->tb; |
| const char *exp_realm = tb->user_baton; |
| |
| tb->result_flags |= TEST_RESULT_AUTHNCB_CALLED; |
| |
| if (code != 401) |
| return SERF_ERROR_ISSUE_IN_TESTSUITE; |
| if (strcmp(exp_realm, realm) != 0) |
| return SERF_ERROR_ISSUE_IN_TESTSUITE; |
| |
| if (strcmp(realm, "<http://localhost:12345> Test Suite") == 0) { |
| *username = "serf"; |
| *password = "serftest"; |
| } else { |
| *username = "serf_newrealm"; |
| *password = "serftest"; |
| } |
| |
| return APR_SUCCESS; |
| } |
| |
| /* Test template, used for both Basic and Digest switch realms test */ |
| static void authentication_switch_realms(CuTest *tc, |
| const char *scheme, |
| const char *authn_attr, |
| const char *authz_attr_test_suite, |
| const char *authz_attr_wrong_realm, |
| const char *authz_attr_new_realm) |
| { |
| test_baton_t *tb; |
| handler_baton_t handler_ctx[2]; |
| int num_requests_sent, num_requests_recvd; |
| test_server_message_t message_list[5]; |
| test_server_action_t action_list[5]; |
| apr_pool_t *test_pool = tc->testBaton; |
| apr_status_t status; |
| |
| |
| message_list[0].text = CHUNKED_REQUEST(1, "1"); |
| message_list[1].text = apr_psprintf(test_pool, |
| "GET / HTTP/1.1" CRLF |
| "Host: localhost:12345" CRLF |
| "Authorization: %s %s" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| CRLF |
| "1" CRLF |
| "1" CRLF |
| "0" CRLF CRLF, scheme, authz_attr_test_suite); |
| message_list[2].text = apr_psprintf(test_pool, |
| "GET / HTTP/1.1" CRLF |
| "Host: localhost:12345" CRLF |
| "Authorization: %s %s" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| CRLF |
| "1" CRLF |
| "2" CRLF |
| "0" CRLF CRLF, scheme, authz_attr_test_suite); |
| /* The client doesn't know that /newrealm/ is in another realm, so it |
| reuses the credentials cached on the connection. */ |
| message_list[3].text = apr_psprintf(test_pool, |
| "GET /newrealm/index.html HTTP/1.1" CRLF |
| "Host: localhost:12345" CRLF |
| "Authorization: %s %s" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| CRLF |
| "1" CRLF |
| "3" CRLF |
| "0" CRLF CRLF, scheme, authz_attr_wrong_realm); |
| message_list[4].text = apr_psprintf(test_pool, |
| "GET /newrealm/index.html HTTP/1.1" CRLF |
| "Host: localhost:12345" CRLF |
| "Authorization: %s %s" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| CRLF |
| "1" CRLF |
| "3" CRLF |
| "0" CRLF CRLF, scheme, authz_attr_new_realm); |
| |
| action_list[0].kind = SERVER_RESPOND; |
| action_list[0].text = apr_psprintf(test_pool, |
| "HTTP/1.1 401 Unauthorized" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| "WWW-Authenticate: %s realm=""Test Suite""%s" CRLF |
| CRLF |
| "0" CRLF CRLF, scheme, authn_attr); |
| action_list[1].kind = SERVER_RESPOND; |
| action_list[1].text = CHUNKED_EMPTY_RESPONSE; |
| action_list[2].kind = SERVER_RESPOND; |
| action_list[2].text = CHUNKED_EMPTY_RESPONSE; |
| action_list[3].kind = SERVER_RESPOND; |
| action_list[3].text = apr_psprintf(test_pool, |
| "HTTP/1.1 401 Unauthorized" CRLF |
| "Transfer-Encoding: chunked" CRLF |
| "WWW-Authenticate: %s realm=""New Realm""%s" CRLF |
| CRLF |
| "0" CRLF CRLF, scheme, authn_attr); |
| action_list[4].kind = SERVER_RESPOND; |
| action_list[4].text = CHUNKED_EMPTY_RESPONSE; |
| |
| |
| /* Set up a test context with a server */ |
| status = test_http_server_setup(&tb, |
| message_list, 5, |
| action_list, 5, 0, NULL, |
| test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| |
| serf_config_authn_types(tb->context, SERF_AUTHN_BASIC | SERF_AUTHN_DIGEST); |
| serf_config_credentials_callback(tb->context, |
| switched_realm_authn_callback); |
| |
| create_new_request(tb, &handler_ctx[0], "GET", "/", 1); |
| |
| /* Test that a request is retried and authentication headers are set |
| correctly. */ |
| num_requests_sent = 1; |
| num_requests_recvd = 2; |
| |
| tb->user_baton = "<http://localhost:12345> Test Suite"; |
| status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, |
| handler_ctx, test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts); |
| CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts); |
| CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts); |
| |
| CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); |
| |
| /* Test that credentials were cached by asserting that the authn callback |
| wasn't called again. */ |
| tb->result_flags = 0; |
| |
| create_new_request(tb, &handler_ctx[0], "GET", "/", 2); |
| status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, |
| handler_ctx, test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| CuAssertTrue(tc, !(tb->result_flags & TEST_RESULT_AUTHNCB_CALLED)); |
| |
| /* Switch realms. Test that serf asks the application for new |
| credentials. */ |
| tb->result_flags = 0; |
| tb->user_baton = "<http://localhost:12345> New Realm"; |
| |
| create_new_request(tb, &handler_ctx[0], "GET", "/newrealm/index.html", 3); |
| status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, |
| handler_ctx, test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); |
| } |
| |
| static void test_basic_switch_realms(CuTest *tc) |
| { |
| authentication_switch_realms(tc, "Basic", "", "c2VyZjpzZXJmdGVzdA==", |
| "c2VyZjpzZXJmdGVzdA==", |
| "c2VyZl9uZXdyZWFsbTpzZXJmdGVzdA=="); |
| } |
| |
| static void test_digest_switch_realms(CuTest *tc) |
| { |
| authentication_switch_realms(tc, "Digest", ",nonce=\"ABCDEF1234567890\"," |
| "opaque=\"myopaque\", algorithm=\"MD5\",qop-options=\"auth\"", |
| /* response hdr attribute for Test Suite realm, uri / */ |
| "realm=\"Test Suite\", username=\"serf\", nonce=\"ABCDEF1234567890\", " |
| "uri=\"/\", response=\"3511a71fec5c02ab1c9212711a8baa58\", " |
| "opaque=\"myopaque\", algorithm=\"MD5\"", |
| /* response hdr attribute for Test Suite realm, uri /newrealm/index.html */ |
| "realm=\"Test Suite\", username=\"serf\", nonce=\"ABCDEF1234567890\", " |
| "uri=\"/newrealm/index.html\", response=\"c6b673cf44ad16ef379930856b607344\", " |
| "opaque=\"myopaque\", algorithm=\"MD5\"", |
| /* response hdr attribute for New Realm realm, uri /newrealm/index.html */ |
| "realm=\"New Realm\", username=\"serf_newrealm\", nonce=\"ABCDEF1234567890\", " |
| "uri=\"/newrealm/index.html\", response=\"f93f07d1412e53c421f66741a89198cb\", " |
| "opaque=\"myopaque\", algorithm=\"MD5\""); |
| } |
| |
| static void test_auth_on_HEAD(CuTest *tc) |
| { |
| test_baton_t *tb; |
| handler_baton_t handler_ctx[2]; |
| int num_requests_sent, num_requests_recvd; |
| apr_status_t status; |
| apr_pool_t *test_pool = tc->testBaton; |
| |
| test_server_message_t message_list[] = { |
| { |
| "HEAD / HTTP/1.1" CRLF |
| "Host: localhost:12345" CRLF |
| CRLF |
| }, |
| { |
| "HEAD / HTTP/1.1" CRLF |
| "Host: localhost:12345" CRLF |
| "Authorization: Basic c2VyZjpzZXJmdGVzdA==" CRLF |
| CRLF |
| }, |
| }; |
| test_server_action_t action_list[] = { |
| { |
| SERVER_RESPOND, |
| "HTTP/1.1 401 Unauthorized" CRLF |
| "WWW-Authenticate: Basic Realm=""Test Suite""" CRLF |
| CRLF |
| }, |
| { |
| SERVER_RESPOND, |
| "HTTP/1.1 200 Ok" CRLF |
| "Content-Type: text/html" CRLF |
| CRLF |
| }, |
| }; |
| |
| /* Set up a test context with a server */ |
| status = test_http_server_setup(&tb, |
| message_list, 2, |
| action_list, 2, 0, NULL, |
| test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| |
| serf_config_authn_types(tb->context, SERF_AUTHN_BASIC); |
| serf_config_credentials_callback(tb->context, basic_authn_callback); |
| |
| create_new_request(tb, &handler_ctx[0], "HEAD", "/", -1); |
| |
| /* Test that a request is retried and authentication headers are set |
| correctly. */ |
| num_requests_sent = 1; |
| num_requests_recvd = 2; |
| |
| status = test_helper_run_requests_no_check(tc, tb, num_requests_sent, |
| handler_ctx, test_pool); |
| CuAssertIntEquals(tc, APR_SUCCESS, status); |
| CuAssertIntEquals(tc, num_requests_recvd, tb->sent_requests->nelts); |
| CuAssertIntEquals(tc, num_requests_recvd, tb->accepted_requests->nelts); |
| CuAssertIntEquals(tc, num_requests_sent, tb->handled_requests->nelts); |
| |
| CuAssertTrue(tc, tb->result_flags & TEST_RESULT_AUTHNCB_CALLED); |
| } |
| |
| /*****************************************************************************/ |
| CuSuite *test_auth(void) |
| { |
| CuSuite *suite = CuSuiteNew(); |
| |
| CuSuiteSetSetupTeardownCallbacks(suite, test_setup, test_teardown); |
| |
| SUITE_ADD_TEST(suite, test_authentication_disabled); |
| SUITE_ADD_TEST(suite, test_unsupported_authentication); |
| SUITE_ADD_TEST(suite, test_basic_authentication); |
| SUITE_ADD_TEST(suite, test_basic_authentication_keepalive_off); |
| SUITE_ADD_TEST(suite, test_digest_authentication); |
| SUITE_ADD_TEST(suite, test_digest_authentication_keepalive_off); |
| SUITE_ADD_TEST(suite, test_basic_switch_realms); |
| SUITE_ADD_TEST(suite, test_digest_switch_realms); |
| SUITE_ADD_TEST(suite, test_auth_on_HEAD); |
| |
| return suite; |
| } |