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// See "SSPI Sample Application" at
6// http://msdn.microsoft.com/en-us/library/aa918273.aspx
7// and "NTLM Security Support Provider" at
8// http://msdn.microsoft.com/en-us/library/aa923611.aspx.
9
10#include "net/http/http_auth_handler_ntlm.h"
11
12#include "base/strings/string_util.h"
13#include "net/base/net_errors.h"
14#include "net/base/net_util.h"
15#include "net/http/http_auth_sspi_win.h"
16#include "net/http/url_security_manager.h"
17
18#pragma comment(lib, "secur32.lib")
19
20namespace net {
21
22HttpAuthHandlerNTLM::HttpAuthHandlerNTLM(
23    SSPILibrary* sspi_library, ULONG max_token_length,
24    URLSecurityManager* url_security_manager)
25    : auth_sspi_(sspi_library, "NTLM", NTLMSP_NAME, max_token_length),
26      url_security_manager_(url_security_manager) {
27}
28
29HttpAuthHandlerNTLM::~HttpAuthHandlerNTLM() {
30}
31
32// Require identity on first pass instead of second.
33bool HttpAuthHandlerNTLM::NeedsIdentity() {
34  return auth_sspi_.NeedsIdentity();
35}
36
37bool HttpAuthHandlerNTLM::AllowsDefaultCredentials() {
38  if (target_ == HttpAuth::AUTH_PROXY)
39    return true;
40  if (!url_security_manager_)
41    return false;
42  return url_security_manager_->CanUseDefaultCredentials(origin_);
43}
44
45HttpAuthHandlerNTLM::Factory::Factory()
46    : max_token_length_(0),
47      first_creation_(true),
48      is_unsupported_(false) {
49}
50
51HttpAuthHandlerNTLM::Factory::~Factory() {
52}
53
54int HttpAuthHandlerNTLM::Factory::CreateAuthHandler(
55    HttpAuthChallengeTokenizer* challenge,
56    HttpAuth::Target target,
57    const GURL& origin,
58    CreateReason reason,
59    int digest_nonce_count,
60    const BoundNetLog& net_log,
61    scoped_ptr<HttpAuthHandler>* handler) {
62  if (is_unsupported_ || reason == CREATE_PREEMPTIVE)
63    return ERR_UNSUPPORTED_AUTH_SCHEME;
64  if (max_token_length_ == 0) {
65    int rv = DetermineMaxTokenLength(sspi_library_.get(), NTLMSP_NAME,
66                                     &max_token_length_);
67    if (rv == ERR_UNSUPPORTED_AUTH_SCHEME)
68      is_unsupported_ = true;
69    if (rv != OK)
70      return rv;
71  }
72  // TODO(cbentzel): Move towards model of parsing in the factory
73  //                 method and only constructing when valid.
74  scoped_ptr<HttpAuthHandler> tmp_handler(
75      new HttpAuthHandlerNTLM(sspi_library_.get(), max_token_length_,
76                              url_security_manager()));
77  if (!tmp_handler->InitFromChallenge(challenge, target, origin, net_log))
78    return ERR_INVALID_RESPONSE;
79  handler->swap(tmp_handler);
80  return OK;
81}
82
83}  // namespace net
84