1// Copyright (c) 2010 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#ifndef NET_HTTP_HTTP_AUTH_HANDLER_NEGOTIATE_H_
6#define NET_HTTP_HTTP_AUTH_HANDLER_NEGOTIATE_H_
7#pragma once
8
9#include <string>
10
11#include "base/string16.h"
12#include "build/build_config.h"
13#include "net/base/address_list.h"
14#include "net/http/http_auth_handler.h"
15#include "net/http/http_auth_handler_factory.h"
16
17#if defined(OS_WIN)
18#include "net/http/http_auth_sspi_win.h"
19#elif defined(OS_POSIX)
20#include "net/http/http_auth_gssapi_posix.h"
21#endif
22
23namespace net {
24
25class HostResolver;
26class SingleRequestHostResolver;
27class URLSecurityManager;
28
29// Handler for WWW-Authenticate: Negotiate protocol.
30//
31// See http://tools.ietf.org/html/rfc4178 and http://tools.ietf.org/html/rfc4559
32// for more information about the protocol.
33
34class HttpAuthHandlerNegotiate : public HttpAuthHandler {
35 public:
36#if defined(OS_WIN)
37  typedef SSPILibrary AuthLibrary;
38  typedef HttpAuthSSPI AuthSystem;
39#elif defined(OS_POSIX)
40  typedef GSSAPILibrary AuthLibrary;
41  typedef HttpAuthGSSAPI AuthSystem;
42#endif
43
44  class Factory : public HttpAuthHandlerFactory {
45   public:
46    Factory();
47    virtual ~Factory();
48
49    // |disable_cname_lookup()| and |set_disable_cname_lookup()| get/set whether
50    // the auth handlers generated by this factory should skip looking up the
51    // canonical DNS name of the the host that they are authenticating to when
52    // generating the SPN. The default value is false.
53    bool disable_cname_lookup() const { return disable_cname_lookup_; }
54    void set_disable_cname_lookup(bool disable_cname_lookup) {
55      disable_cname_lookup_ = disable_cname_lookup;
56    }
57
58    // |use_port()| and |set_use_port()| get/set whether the auth handlers
59    // generated by this factory should include the port number of the server
60    // they are authenticating to when constructing a Kerberos SPN. The default
61    // value is false.
62    bool use_port() const { return use_port_; }
63    void set_use_port(bool use_port) { use_port_ = use_port; }
64
65    void set_host_resolver(HostResolver* host_resolver);
66
67    // Sets the system library to use, thereby assuming ownership of
68    // |auth_library|.
69    void set_library(AuthLibrary* auth_library) {
70      auth_library_.reset(auth_library);
71    }
72
73    virtual int CreateAuthHandler(HttpAuth::ChallengeTokenizer* challenge,
74                                  HttpAuth::Target target,
75                                  const GURL& origin,
76                                  CreateReason reason,
77                                  int digest_nonce_count,
78                                  const BoundNetLog& net_log,
79                                  scoped_ptr<HttpAuthHandler>* handler);
80
81   private:
82    bool disable_cname_lookup_;
83    bool use_port_;
84    HostResolver* resolver_;
85#if defined(OS_WIN)
86    ULONG max_token_length_;
87    bool first_creation_;
88    bool is_unsupported_;
89#endif
90    scoped_ptr<AuthLibrary> auth_library_;
91  };
92
93  HttpAuthHandlerNegotiate(AuthLibrary* sspi_library,
94#if defined(OS_WIN)
95                           ULONG max_token_length,
96#endif
97                           URLSecurityManager* url_security_manager,
98                           HostResolver* host_resolver,
99                           bool disable_cname_lookup,
100                           bool use_port);
101
102  virtual ~HttpAuthHandlerNegotiate();
103
104  // These are public for unit tests
105  std::wstring CreateSPN(const AddressList& address_list, const GURL& orign);
106  const std::wstring& spn() const { return spn_; }
107
108  // HttpAuthHandler:
109  virtual HttpAuth::AuthorizationResult HandleAnotherChallenge(
110      HttpAuth::ChallengeTokenizer* challenge);
111  virtual bool NeedsIdentity();
112  virtual bool AllowsDefaultCredentials();
113
114 protected:
115  virtual bool Init(HttpAuth::ChallengeTokenizer* challenge);
116
117  virtual int GenerateAuthTokenImpl(const string16* username,
118                                    const string16* password,
119                                    const HttpRequestInfo* request,
120                                    CompletionCallback* callback,
121                                    std::string* auth_token);
122
123 private:
124  enum State {
125    STATE_RESOLVE_CANONICAL_NAME,
126    STATE_RESOLVE_CANONICAL_NAME_COMPLETE,
127    STATE_GENERATE_AUTH_TOKEN,
128    STATE_GENERATE_AUTH_TOKEN_COMPLETE,
129    STATE_NONE,
130  };
131
132  void OnIOComplete(int result);
133  void DoCallback(int result);
134  int DoLoop(int result);
135
136  int DoResolveCanonicalName();
137  int DoResolveCanonicalNameComplete(int rv);
138  int DoGenerateAuthToken();
139  int DoGenerateAuthTokenComplete(int rv);
140  bool CanDelegate() const;
141
142  AuthSystem auth_system_;
143  bool disable_cname_lookup_;
144  bool use_port_;
145  CompletionCallbackImpl<HttpAuthHandlerNegotiate> io_callback_;
146  HostResolver* const resolver_;
147
148  // Members which are needed for DNS lookup + SPN.
149  AddressList address_list_;
150  scoped_ptr<SingleRequestHostResolver> single_resolve_;
151
152  // Things which should be consistent after first call to GenerateAuthToken.
153  bool already_called_;
154  bool has_username_and_password_;
155  string16 username_;
156  string16 password_;
157  std::wstring spn_;
158
159  // Things which vary each round.
160  CompletionCallback* user_callback_;
161  std::string* auth_token_;
162
163  State next_state_;
164
165  const URLSecurityManager* url_security_manager_;
166};
167
168}  // namespace net
169
170#endif  // NET_HTTP_HTTP_AUTH_HANDLER_NEGOTIATE_H_
171