summaryrefslogtreecommitdiff
path: root/chromium/net/ntlm/ntlm_constants.h
blob: 12f181ba61793fb9d4f8ae9bf38ce2681c351174 (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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_NTLM_NTLM_CONSTANTS_H_
#define NET_NTLM_NTLM_CONSTANTS_H_

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

#include <vector>

#include "net/base/net_export.h"

namespace net::ntlm {

// A security buffer is a structure within an NTLM message that indicates
// the offset from the beginning of the message and the length of a payload
// that occurs later in the message. Within the raw message there is also
// an additional field, however the field is always written with the same
// value as length, and readers must always ignore it.
struct SecurityBuffer {
  SecurityBuffer(uint32_t offset, uint16_t length)
      : offset(offset), length(length) {}
  SecurityBuffer() : SecurityBuffer(0, 0) {}

  uint32_t offset;
  uint16_t length;
};

struct NtlmFeatures {
  explicit NtlmFeatures(bool enable_NTLMv2) : enable_NTLMv2(enable_NTLMv2) {}

  // Whether the use NTLMv2.
  bool enable_NTLMv2 = true;

  // Enables Message Integrity Check (MIC). This flag is ignored if
  // enable_NTLMv2 is false.
  bool enable_MIC = true;

  // Enables Extended Protection for Authentication (EPA). This flag is
  // ignored if enable_NTLMv2 is false.
  bool enable_EPA = true;
};

// There are 3 types of messages in NTLM. The message type is a field in
// every NTLM message header. See [MS-NLMP] Section 2.2.
enum class MessageType : uint32_t {
  kNegotiate = 0x01,
  kChallenge = 0x02,
  kAuthenticate = 0x03,
};

// Defined in [MS-NLMP] Section 2.2.2.5
// Only the used subset is defined.
enum class NegotiateFlags : uint32_t {
  kNone = 0,
  kUnicode = 0x01,
  kOem = 0x02,
  kRequestTarget = 0x04,
  kNtlm = 0x200,
  kAlwaysSign = 0x8000,
  kExtendedSessionSecurity = 0x80000,
  kTargetInfo = 0x800000,
};

constexpr NegotiateFlags operator|(NegotiateFlags lhs, NegotiateFlags rhs) {
  using TFlagsInt = std::underlying_type<NegotiateFlags>::type;

  return static_cast<NegotiateFlags>(static_cast<TFlagsInt>(lhs) |
                                     static_cast<TFlagsInt>(rhs));
}

constexpr NegotiateFlags operator&(NegotiateFlags lhs, NegotiateFlags rhs) {
  using TFlagsInt = std::underlying_type<NegotiateFlags>::type;

  return static_cast<NegotiateFlags>(static_cast<TFlagsInt>(lhs) &
                                     static_cast<TFlagsInt>(rhs));
}

// Identifies the payload type in an AV Pair. See [MS-NLMP] 2.2.2.1
enum class TargetInfoAvId : uint16_t {
  kEol = 0x0000,
  kServerName = 0x00001,
  kDomainName = 0x00002,
  kFlags = 0x0006,
  kTimestamp = 0x0007,
  kTargetName = 0x0009,
  kChannelBindings = 0x000A,
};

// Flags used in an TargetInfoAvId::kFlags AV Pair. See [MS-NLMP] 2.2.2.1
enum class TargetInfoAvFlags : uint32_t {
  kNone = 0,
  kMicPresent = 0x00000002,
};

using TAvFlagsInt = std::underlying_type<TargetInfoAvFlags>::type;

constexpr TargetInfoAvFlags operator|(TargetInfoAvFlags lhs,
                                      TargetInfoAvFlags rhs) {
  return static_cast<TargetInfoAvFlags>(static_cast<TAvFlagsInt>(lhs) |
                                        static_cast<TAvFlagsInt>(rhs));
}

constexpr TargetInfoAvFlags operator&(TargetInfoAvFlags lhs,
                                      TargetInfoAvFlags rhs) {
  return static_cast<TargetInfoAvFlags>(static_cast<TAvFlagsInt>(lhs) &
                                        static_cast<TAvFlagsInt>(rhs));
}

// An AV Pair is a structure that appears inside the target info field. It
// consists of an |avid| to identify the data type and an |avlen| specifying
// the size of the payload. Following that is |avlen| bytes of inline payload.
// AV Pairs are concatenated together and a special terminator with |avid|
// equal to |kEol| and |avlen| equal to zero signals that no further pairs
// follow. See [MS-NLMP] 2.2.2.1
//
// AV Pairs from the Challenge message are read from the challenge message
// and a potentially modified version is written into the authenticate
// message. In some cases the existing AV Pair is modified, eg. flags. In
// some cases new AV Pairs are add, eg. channel bindings and spn.
//
// For simplicity of processing two special fields |flags|, and |timestamp|
// are populated during the initial parsing phase for AVIDs |kFlags| and
// |kTimestamp| respectively. This avoids subsequent code having to
// manipulate the payload value through the buffer directly. For all
// other AvPairs the value of these 2 fields is undefined and the payload
// is in the |buffer| field. For these fields the payload is copied verbatim
// and it's content is not read or validated in any way.
struct NET_EXPORT_PRIVATE AvPair {
  AvPair();
  AvPair(TargetInfoAvId avid, uint16_t avlen);
  AvPair(TargetInfoAvId avid, std::vector<uint8_t> buffer);
  AvPair(const AvPair& other);
  AvPair(AvPair&& other);
  ~AvPair();

  AvPair& operator=(const AvPair& other);
  AvPair& operator=(AvPair&& other);

  std::vector<uint8_t> buffer;
  uint64_t timestamp;
  TargetInfoAvFlags flags;
  TargetInfoAvId avid;
  uint16_t avlen;
};

static constexpr uint8_t kSignature[] = "NTLMSSP";
static constexpr size_t kSignatureLen = std::size(kSignature);
static constexpr uint16_t kProofInputVersionV2 = 0x0101;
static constexpr size_t kSecurityBufferLen =
    (2 * sizeof(uint16_t)) + sizeof(uint32_t);
static constexpr size_t kNegotiateMessageLen = 32;
static constexpr size_t kMinChallengeHeaderLen = 32;
static constexpr size_t kChallengeHeaderLen = 48;
static constexpr size_t kResponseLenV1 = 24;
static constexpr size_t kChallengeLen = 8;
static constexpr size_t kVersionFieldLen = 8;
static constexpr size_t kNtlmHashLen = 16;
static constexpr size_t kNtlmProofLenV2 = kNtlmHashLen;
static constexpr size_t kSessionKeyLenV2 = kNtlmHashLen;
static constexpr size_t kMicLenV2 = kNtlmHashLen;
static constexpr size_t kChannelBindingsHashLen = kNtlmHashLen;
static constexpr size_t kEpaUnhashedStructHeaderLen = 20;
static constexpr size_t kProofInputLenV2 = 28;
static constexpr size_t kAvPairHeaderLen = 2 * sizeof(uint16_t);
static constexpr size_t kNtlmResponseHeaderLenV2 =
    kNtlmProofLenV2 + kProofInputLenV2;
static constexpr size_t kAuthenticateHeaderLenV1 = 64;
static constexpr size_t kMicOffsetV2 = 72;
static constexpr size_t kAuthenticateHeaderLenV2 = 88;

static constexpr size_t kMaxFqdnLen = 255;
static constexpr size_t kMaxUsernameLen = 104;
static constexpr size_t kMaxPasswordLen = 256;

static constexpr NegotiateFlags kNegotiateMessageFlags =
    NegotiateFlags::kUnicode | NegotiateFlags::kOem |
    NegotiateFlags::kRequestTarget | NegotiateFlags::kNtlm |
    NegotiateFlags::kAlwaysSign | NegotiateFlags::kExtendedSessionSecurity;

}  // namespace net::ntlm

#endif  // NET_NTLM_NTLM_CONSTANTS_H_