1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/memory/scoped_ptr.h"
6#include "net/base/net_errors.h"
7#include "net/dns/mock_host_resolver.h"
8#include "net/http/http_auth_handler.h"
9#include "net/http/http_auth_handler_factory.h"
10#include "net/http/mock_allow_url_security_manager.h"
11#include "net/http/url_security_manager.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace net {
15
16namespace {
17
18class MockHttpAuthHandlerFactory : public HttpAuthHandlerFactory {
19 public:
20  explicit MockHttpAuthHandlerFactory(int return_code) :
21      return_code_(return_code) {}
22  virtual ~MockHttpAuthHandlerFactory() {}
23
24  virtual int CreateAuthHandler(HttpAuthChallengeTokenizer* challenge,
25                                HttpAuth::Target target,
26                                const GURL& origin,
27                                CreateReason reason,
28                                int nonce_count,
29                                const BoundNetLog& net_log,
30                                scoped_ptr<HttpAuthHandler>* handler) OVERRIDE {
31    handler->reset();
32    return return_code_;
33  }
34
35 private:
36  int return_code_;
37};
38
39}  // namespace
40
41TEST(HttpAuthHandlerFactoryTest, RegistryFactory) {
42  HttpAuthHandlerRegistryFactory registry_factory;
43  GURL gurl("www.google.com");
44  const int kBasicReturnCode = ERR_INVALID_SPDY_STREAM;
45  MockHttpAuthHandlerFactory* mock_factory_basic =
46      new MockHttpAuthHandlerFactory(kBasicReturnCode);
47
48  const int kDigestReturnCode = ERR_PAC_SCRIPT_FAILED;
49  MockHttpAuthHandlerFactory* mock_factory_digest =
50      new MockHttpAuthHandlerFactory(kDigestReturnCode);
51
52  const int kDigestReturnCodeReplace = ERR_SYN_REPLY_NOT_RECEIVED;
53  MockHttpAuthHandlerFactory* mock_factory_digest_replace =
54      new MockHttpAuthHandlerFactory(kDigestReturnCodeReplace);
55
56  scoped_ptr<HttpAuthHandler> handler;
57
58  // No schemes should be supported in the beginning.
59  EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
60            registry_factory.CreateAuthHandlerFromString(
61                "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
62
63  // Test what happens with a single scheme.
64  registry_factory.RegisterSchemeFactory("Basic", mock_factory_basic);
65  EXPECT_EQ(kBasicReturnCode,
66            registry_factory.CreateAuthHandlerFromString(
67                "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
68  EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME,
69            registry_factory.CreateAuthHandlerFromString(
70                "Digest", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(),
71                &handler));
72
73  // Test multiple schemes
74  registry_factory.RegisterSchemeFactory("Digest", mock_factory_digest);
75  EXPECT_EQ(kBasicReturnCode,
76            registry_factory.CreateAuthHandlerFromString(
77                "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
78  EXPECT_EQ(kDigestReturnCode,
79            registry_factory.CreateAuthHandlerFromString(
80                "Digest", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(),
81                &handler));
82
83  // Test case-insensitivity
84  EXPECT_EQ(kBasicReturnCode,
85            registry_factory.CreateAuthHandlerFromString(
86                "basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
87
88  // Test replacement of existing auth scheme
89  registry_factory.RegisterSchemeFactory("Digest", mock_factory_digest_replace);
90  EXPECT_EQ(kBasicReturnCode,
91            registry_factory.CreateAuthHandlerFromString(
92                "Basic", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(), &handler));
93  EXPECT_EQ(kDigestReturnCodeReplace,
94            registry_factory.CreateAuthHandlerFromString(
95                "Digest", HttpAuth::AUTH_SERVER, gurl, BoundNetLog(),
96                &handler));
97}
98
99TEST(HttpAuthHandlerFactoryTest, DefaultFactory) {
100  scoped_ptr<HostResolver> host_resolver(new MockHostResolver());
101  MockAllowURLSecurityManager url_security_manager;
102  scoped_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory(
103      HttpAuthHandlerFactory::CreateDefault(host_resolver.get()));
104  http_auth_handler_factory->SetURLSecurityManager(
105      "negotiate", &url_security_manager);
106  GURL server_origin("http://www.example.com");
107  GURL proxy_origin("http://cache.example.com:3128");
108  {
109    scoped_ptr<HttpAuthHandler> handler;
110    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
111        "Basic realm=\"FooBar\"",
112        HttpAuth::AUTH_SERVER,
113        server_origin,
114        BoundNetLog(),
115        &handler);
116    EXPECT_EQ(OK, rv);
117    ASSERT_FALSE(handler.get() == NULL);
118    EXPECT_EQ(HttpAuth::AUTH_SCHEME_BASIC, handler->auth_scheme());
119    EXPECT_STREQ("FooBar", handler->realm().c_str());
120    EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
121    EXPECT_FALSE(handler->encrypts_identity());
122    EXPECT_FALSE(handler->is_connection_based());
123  }
124  {
125    scoped_ptr<HttpAuthHandler> handler;
126    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
127        "UNSUPPORTED realm=\"FooBar\"",
128        HttpAuth::AUTH_SERVER,
129        server_origin,
130        BoundNetLog(),
131        &handler);
132    EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, rv);
133    EXPECT_TRUE(handler.get() == NULL);
134  }
135  {
136    scoped_ptr<HttpAuthHandler> handler;
137    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
138        "Digest realm=\"FooBar\", nonce=\"xyz\"",
139        HttpAuth::AUTH_PROXY,
140        proxy_origin,
141        BoundNetLog(),
142        &handler);
143    EXPECT_EQ(OK, rv);
144    ASSERT_FALSE(handler.get() == NULL);
145    EXPECT_EQ(HttpAuth::AUTH_SCHEME_DIGEST, handler->auth_scheme());
146    EXPECT_STREQ("FooBar", handler->realm().c_str());
147    EXPECT_EQ(HttpAuth::AUTH_PROXY, handler->target());
148    EXPECT_TRUE(handler->encrypts_identity());
149    EXPECT_FALSE(handler->is_connection_based());
150  }
151  {
152    scoped_ptr<HttpAuthHandler> handler;
153    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
154        "NTLM",
155        HttpAuth::AUTH_SERVER,
156        server_origin,
157        BoundNetLog(),
158        &handler);
159    EXPECT_EQ(OK, rv);
160    ASSERT_FALSE(handler.get() == NULL);
161    EXPECT_EQ(HttpAuth::AUTH_SCHEME_NTLM, handler->auth_scheme());
162    EXPECT_STREQ("", handler->realm().c_str());
163    EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
164    EXPECT_TRUE(handler->encrypts_identity());
165    EXPECT_TRUE(handler->is_connection_based());
166  }
167  {
168    scoped_ptr<HttpAuthHandler> handler;
169    int rv = http_auth_handler_factory->CreateAuthHandlerFromString(
170        "Negotiate",
171        HttpAuth::AUTH_SERVER,
172        server_origin,
173        BoundNetLog(),
174        &handler);
175#if defined(USE_KERBEROS)
176    EXPECT_EQ(OK, rv);
177    ASSERT_FALSE(handler.get() == NULL);
178    EXPECT_EQ(HttpAuth::AUTH_SCHEME_NEGOTIATE, handler->auth_scheme());
179    EXPECT_STREQ("", handler->realm().c_str());
180    EXPECT_EQ(HttpAuth::AUTH_SERVER, handler->target());
181    EXPECT_TRUE(handler->encrypts_identity());
182    EXPECT_TRUE(handler->is_connection_based());
183#else
184    EXPECT_EQ(ERR_UNSUPPORTED_AUTH_SCHEME, rv);
185    EXPECT_TRUE(handler.get() == NULL);
186#endif  // defined(USE_KERBEROS)
187  }
188}
189
190}  // namespace net
191