15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/net/spdyproxy/http_auth_handler_spdyproxy.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_info.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kValidOrigin[] = "https://www.proxy.com/";
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kValidChallenge[] = "SpdyProxy realm=\"SpdyProxy\", "
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ps=\"1-2-3-4\"";
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace spdyproxy {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::ERR_INVALID_RESPONSE;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::ERR_UNSUPPORTED_AUTH_SCHEME;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::OK;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::AuthCredentials;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::BoundNetLog;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::CompletionCallback;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::Error;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::HttpAuth;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::HttpAuthHandler;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::HttpRequestInfo;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthHandlerSpdyProxyTest, GenerateAuthToken) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verifies that challenge parsing is expected as described in individual
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cases below.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const struct {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Error err1, err2;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* origin;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* challenge;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* username;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* sid;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_credentials;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } tests[] = {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A well-formed challenge where a sid is provided produces a valid
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // response header echoing the sid and ps token.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { OK, OK,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kValidOrigin,
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kValidChallenge,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "",
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "sid-string",
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "SpdyProxy ps=\"1-2-3-4\", sid=\"sid-string\"",},
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A non-SSL origin returns ERR_UNSUPPORTED_AUTH_SCHEME.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { ERR_UNSUPPORTED_AUTH_SCHEME, OK,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "http://www.proxy.com/", "", "", "", "",},
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // An SSL origin not matching the authorized origin returns
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ERR_UNSUPPORTED_AUTH_SCHEME.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { ERR_UNSUPPORTED_AUTH_SCHEME, OK,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "https://www.unconfigured.com/", "", "", "", "",},
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Absent ps token yields ERR_INVALID_RESPONSE.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      { ERR_INVALID_RESPONSE, OK,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kValidOrigin, "SpdyProxy realm=\"SpdyProxy\"", "", "", "",},
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL origin(tests[i].origin);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL authorized_origin(kValidOrigin);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuthHandlerSpdyProxy::Factory factory(authorized_origin);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpAuthHandler> spdyproxy;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].err1, factory.CreateAuthHandlerFromString(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        tests[i].challenge, HttpAuth::AUTH_PROXY, origin, BoundNetLog(),
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &spdyproxy));
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tests[i].err1 != OK) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AuthCredentials credentials(ASCIIToUTF16(tests[i].username),
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                ASCIIToUTF16(tests[i].sid));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestInfo request_info;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string auth_token;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = spdyproxy->GenerateAuthToken(&credentials, &request_info,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          CompletionCallback(), &auth_token);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].err2, rv);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tests[i].err2 != OK) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_STREQ(tests[i].expected_credentials, auth_token.c_str());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthHandlerSpdyProxyTest, NonProxyAuthTypeFails) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verifies that an authorization request fails if requested by an ordinary
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // site. (i.e., HttpAuth::AUTH_SERVER)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL origin(kValidOrigin);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL accepted_origin(kValidOrigin);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthHandlerSpdyProxy::Factory factory(accepted_origin);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpAuthHandler> spdyproxy;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, factory.CreateAuthHandlerFromString(
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kValidChallenge, HttpAuth::AUTH_SERVER, origin,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BoundNetLog(), &spdyproxy));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthHandlerSpdyProxyTest, HandleAnotherChallenge) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verifies that any repeat challenge is treated as a failure.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL origin(kValidOrigin);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL accepted_origin(kValidOrigin);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthHandlerSpdyProxy::Factory factory(accepted_origin);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<HttpAuthHandler> spdyproxy;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, factory.CreateAuthHandlerFromString(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kValidChallenge, HttpAuth::AUTH_PROXY, origin,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BoundNetLog(), &spdyproxy));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string challenge(kValidChallenge);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuth::ChallengeTokenizer tok(challenge.begin(),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   challenge.end());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(HttpAuth::AUTHORIZATION_RESULT_REJECT,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            spdyproxy->HandleAnotherChallenge(&tok));
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(HttpAuthHandlerSpdyProxyTest, ParseChallenge) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verifies that various challenge strings are parsed appropriately as
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // described below.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const struct {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* challenge;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int expected_rv;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_ps;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* expected_realm;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } tests[] = {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Absent parameters fails.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "SpdyProxy", ERR_INVALID_RESPONSE, "", "", },
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Empty parameters fails.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "SpdyProxy ps=\"\"", ERR_INVALID_RESPONSE, "", "", },
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Valid challenge parses successfully.
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { kValidChallenge, OK, "1-2-3-4", "SpdyProxy", },
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL origin(kValidOrigin);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL accepted_origin(kValidOrigin);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpAuthHandlerSpdyProxy::Factory factory(accepted_origin);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string challenge = tests[i].challenge;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<HttpAuthHandler> spdyproxy;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = factory.CreateAuthHandlerFromString(
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        challenge, HttpAuth::AUTH_PROXY, origin, BoundNetLog(), &spdyproxy);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(tests[i].expected_rv, rv);
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == OK) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(tests[i].expected_realm, spdyproxy->realm());
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpAuthHandlerSpdyProxy* as_spdyproxy =
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<HttpAuthHandlerSpdyProxy*>(spdyproxy.get());
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      EXPECT_EQ(tests[i].expected_ps,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                as_spdyproxy->ps_token_);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace spdyproxy
162