summaryrefslogtreecommitdiff
path: root/chromium/net/ntlm/ntlm_client.h
blob: 5ef1bd4f8a6bec075af1fdbdf6ce553c66c63c28 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol
// Specification version 28.0 [1], an unofficial NTLM reference [2], and a
// blog post describing Extended Protection for Authentication [3].
//
// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
// [2] http://davenport.sourceforge.net/ntlm.html
// [3]
// https://blogs.msdn.microsoft.com/openspecification/2013/03/26/ntlm-and-channel-binding-hash-aka-extended-protection-for-authentication/

#ifndef NET_BASE_NTLM_CLIENT_H_
#define NET_BASE_NTLM_CLIENT_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <string>

#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/ntlm/ntlm_constants.h"

namespace net {
namespace ntlm {

// Provides an implementation of an NTLMv1 or NTLMv2 Client with support
// for MIC and EPA [1]. This implementation does not support the key exchange,
// signing or sealing feature as the NTLMSSP_NEGOTIATE_KEY_EXCH flag is never
// negotiated.
//
// [1] -
// https://support.microsoft.com/en-us/help/968389/extended-protection-for-authentication
class NET_EXPORT_PRIVATE NtlmClient {
 public:
  // Pass feature flags to enable/disable NTLMv2 and additional NTLMv2
  // features such as Extended Protection for Authentication (EPA) and Message
  // Integrity Check (MIC).
  explicit NtlmClient(NtlmFeatures features);

  ~NtlmClient();

  bool IsNtlmV2() const { return features_.enable_NTLMv2; }

  bool IsMicEnabled() const { return IsNtlmV2() && features_.enable_MIC; }

  bool IsEpaEnabled() const { return IsNtlmV2() && features_.enable_EPA; }

  // Returns a |Buffer| containing the Negotiate message.
  Buffer GetNegotiateMessage() const;

  // Returns a |Buffer| containing the Authenticate message. If the method
  // fails an empty |Buffer| is returned.
  //
  // |username| is treated case insensitively by NTLM however the mechanism
  // to uppercase is not clearly defined. In this implementation the default
  // locale is used. Additionally for names longer than 20 characters, the
  // fully qualified name in the new '@' format must be used.
  // eg. very_long_name@domain.com. Names shorter than 20 characters can
  // optionally omit the '@domain.com' part.
  // |hostname| can be a short NetBIOS name or an FQDN, however the server will
  // only inspect this field if the default domain policy is to restrict NTLM.
  // In this case the hostname will be compared to a whitelist stored in this
  // group policy [1].
  // |channel_bindings| is a string supplied out of band (usually from a web
  // browser) and is a (21+sizeof(hash)) byte ASCII string, where 'hash' is
  // usually a SHA-256 of the servers certificate, but may be another hash
  // algorithm. The format as defined by RFC 5929 Section 4 is shown below;
  //
  // [0-20]                 - "tls-server-end-point:"   (Literal string)
  // [21-(20+sizeof(hash)]  - HASH(server_certificate)  (Certificate hash)
  //
  // |spn| is a string supplied out of band (usually from a web browser) and
  // is a Service  Principal Name [2]. For NTLM over HTTP the value of this
  // string will usually be "HTTP/<hostname>".
  // |client_time| 64 bit Windows timestamp defined as the number of
  // 100 nanosecond ticks since midnight Jan 01, 1601 (UTC). If the server does
  // not send a timestamp, the client timestamp is used in the Proof Input
  // instead.
  // |client_challenge| must contain 8 bytes of random data.
  // |server_challenge_message| is the full content of the challenge message
  // sent by the server.
  //
  // [1] - https://technet.microsoft.com/en-us/library/jj852267(v=ws.11).aspx
  Buffer GenerateAuthenticateMessage(
      const base::string16& domain,
      const base::string16& username,
      const base::string16& password,
      const std::string& hostname,
      const std::string& channel_bindings,
      const std::string& spn,
      uint64_t client_time,
      const uint8_t* client_challenge,
      const Buffer& server_challenge_message) const;

  // Simplified method for NTLMv1 which does not require |channel_bindings|,
  // |spn|, or |client_time|. See |GenerateAuthenticateMessage| for more
  // details.
  Buffer GenerateAuthenticateMessageV1(
      const base::string16& domain,
      const base::string16& username,
      const base::string16& password,
      const std::string& hostname,
      const uint8_t* client_challenge,
      const Buffer& server_challenge_message) const {
    DCHECK(!IsNtlmV2());

    return GenerateAuthenticateMessage(
        domain, username, password, hostname, std::string(), std::string(), 0,
        client_challenge, server_challenge_message);
  }

 private:
  // Returns the length of the Authenticate message based on the length of the
  // variable length parts of the message and whether Unicode support was
  // negotiated.
  size_t CalculateAuthenticateMessageLength(
      bool is_unicode,
      const base::string16& domain,
      const base::string16& username,
      const std::string& hostname,
      size_t updated_target_info_len) const;

  void CalculatePayloadLayout(bool is_unicode,
                              const base::string16& domain,
                              const base::string16& username,
                              const std::string& hostname,
                              size_t updated_target_info_len,
                              SecurityBuffer* lm_info,
                              SecurityBuffer* ntlm_info,
                              SecurityBuffer* domain_info,
                              SecurityBuffer* username_info,
                              SecurityBuffer* hostname_info,
                              SecurityBuffer* session_key_info,
                              size_t* authenticate_message_len) const;

  // Returns the length of the header part of the Authenticate message.
  size_t GetAuthenticateHeaderLength() const;

  // Returns the length of the NTLM response.
  size_t GetNtlmResponseLength(size_t updated_target_info_len) const;

  // Generates the negotiate message (which is always the same) into
  // |negotiate_message_|.
  void GenerateNegotiateMessage();

  NtlmFeatures features_;
  NegotiateFlags negotiate_flags_;
  Buffer negotiate_message_;

  DISALLOW_COPY_AND_ASSIGN(NtlmClient);
};

}  // namespace ntlm
}  // namespace net

#endif  // NET_BASE_NTLM_CLIENT_H_