xref: /aosp_15_r20/external/cronet/net/ntlm/ntlm_constants.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2017 The Chromium Authors
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_NTLM_NTLM_CONSTANTS_H_
6 #define NET_NTLM_NTLM_CONSTANTS_H_
7 
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <type_traits>
11 
12 #include <vector>
13 
14 #include "net/base/net_export.h"
15 
16 namespace net::ntlm {
17 
18 // A security buffer is a structure within an NTLM message that indicates
19 // the offset from the beginning of the message and the length of a payload
20 // that occurs later in the message. Within the raw message there is also
21 // an additional field, however the field is always written with the same
22 // value as length, and readers must always ignore it.
23 struct SecurityBuffer {
SecurityBufferSecurityBuffer24   SecurityBuffer(uint32_t offset, uint16_t length)
25       : offset(offset), length(length) {}
SecurityBufferSecurityBuffer26   SecurityBuffer() : SecurityBuffer(0, 0) {}
27 
28   uint32_t offset;
29   uint16_t length;
30 };
31 
32 struct NtlmFeatures {
NtlmFeaturesNtlmFeatures33   explicit NtlmFeatures(bool enable_NTLMv2) : enable_NTLMv2(enable_NTLMv2) {}
34 
35   // Whether the use NTLMv2.
36   bool enable_NTLMv2 = true;
37 
38   // Enables Message Integrity Check (MIC). This flag is ignored if
39   // enable_NTLMv2 is false.
40   bool enable_MIC = true;
41 
42   // Enables Extended Protection for Authentication (EPA). This flag is
43   // ignored if enable_NTLMv2 is false.
44   bool enable_EPA = true;
45 };
46 
47 // There are 3 types of messages in NTLM. The message type is a field in
48 // every NTLM message header. See [MS-NLMP] Section 2.2.
49 enum class MessageType : uint32_t {
50   kNegotiate = 0x01,
51   kChallenge = 0x02,
52   kAuthenticate = 0x03,
53 };
54 
55 // Defined in [MS-NLMP] Section 2.2.2.5
56 // Only the used subset is defined.
57 enum class NegotiateFlags : uint32_t {
58   kNone = 0,
59   kUnicode = 0x01,
60   kOem = 0x02,
61   kRequestTarget = 0x04,
62   kNtlm = 0x200,
63   kAlwaysSign = 0x8000,
64   kExtendedSessionSecurity = 0x80000,
65   kTargetInfo = 0x800000,
66 };
67 
68 constexpr NegotiateFlags operator|(NegotiateFlags lhs, NegotiateFlags rhs) {
69   using TFlagsInt = std::underlying_type<NegotiateFlags>::type;
70 
71   return static_cast<NegotiateFlags>(static_cast<TFlagsInt>(lhs) |
72                                      static_cast<TFlagsInt>(rhs));
73 }
74 
75 constexpr NegotiateFlags operator&(NegotiateFlags lhs, NegotiateFlags rhs) {
76   using TFlagsInt = std::underlying_type<NegotiateFlags>::type;
77 
78   return static_cast<NegotiateFlags>(static_cast<TFlagsInt>(lhs) &
79                                      static_cast<TFlagsInt>(rhs));
80 }
81 
82 // Identifies the payload type in an AV Pair. See [MS-NLMP] 2.2.2.1
83 enum class TargetInfoAvId : uint16_t {
84   kEol = 0x0000,
85   kServerName = 0x00001,
86   kDomainName = 0x00002,
87   kFlags = 0x0006,
88   kTimestamp = 0x0007,
89   kTargetName = 0x0009,
90   kChannelBindings = 0x000A,
91 };
92 
93 // Flags used in an TargetInfoAvId::kFlags AV Pair. See [MS-NLMP] 2.2.2.1
94 enum class TargetInfoAvFlags : uint32_t {
95   kNone = 0,
96   kMicPresent = 0x00000002,
97 };
98 
99 using TAvFlagsInt = std::underlying_type<TargetInfoAvFlags>::type;
100 
101 constexpr TargetInfoAvFlags operator|(TargetInfoAvFlags lhs,
102                                       TargetInfoAvFlags rhs) {
103   return static_cast<TargetInfoAvFlags>(static_cast<TAvFlagsInt>(lhs) |
104                                         static_cast<TAvFlagsInt>(rhs));
105 }
106 
107 constexpr TargetInfoAvFlags operator&(TargetInfoAvFlags lhs,
108                                       TargetInfoAvFlags rhs) {
109   return static_cast<TargetInfoAvFlags>(static_cast<TAvFlagsInt>(lhs) &
110                                         static_cast<TAvFlagsInt>(rhs));
111 }
112 
113 // An AV Pair is a structure that appears inside the target info field. It
114 // consists of an |avid| to identify the data type and an |avlen| specifying
115 // the size of the payload. Following that is |avlen| bytes of inline payload.
116 // AV Pairs are concatenated together and a special terminator with |avid|
117 // equal to |kEol| and |avlen| equal to zero signals that no further pairs
118 // follow. See [MS-NLMP] 2.2.2.1
119 //
120 // AV Pairs from the Challenge message are read from the challenge message
121 // and a potentially modified version is written into the authenticate
122 // message. In some cases the existing AV Pair is modified, eg. flags. In
123 // some cases new AV Pairs are add, eg. channel bindings and spn.
124 //
125 // For simplicity of processing two special fields |flags|, and |timestamp|
126 // are populated during the initial parsing phase for AVIDs |kFlags| and
127 // |kTimestamp| respectively. This avoids subsequent code having to
128 // manipulate the payload value through the buffer directly. For all
129 // other AvPairs the value of these 2 fields is undefined and the payload
130 // is in the |buffer| field. For these fields the payload is copied verbatim
131 // and it's content is not read or validated in any way.
132 struct NET_EXPORT_PRIVATE AvPair {
133   AvPair();
134   AvPair(TargetInfoAvId avid, uint16_t avlen);
135   AvPair(TargetInfoAvId avid, std::vector<uint8_t> buffer);
136   AvPair(const AvPair& other);
137   AvPair(AvPair&& other);
138   ~AvPair();
139 
140   AvPair& operator=(const AvPair& other);
141   AvPair& operator=(AvPair&& other);
142 
143   std::vector<uint8_t> buffer;
144   uint64_t timestamp;
145   TargetInfoAvFlags flags;
146   TargetInfoAvId avid;
147   uint16_t avlen;
148 };
149 
150 static constexpr uint8_t kSignature[] = "NTLMSSP";
151 static constexpr size_t kSignatureLen = std::size(kSignature);
152 static constexpr uint16_t kProofInputVersionV2 = 0x0101;
153 static constexpr size_t kSecurityBufferLen =
154     (2 * sizeof(uint16_t)) + sizeof(uint32_t);
155 static constexpr size_t kNegotiateMessageLen = 32;
156 static constexpr size_t kMinChallengeHeaderLen = 32;
157 static constexpr size_t kChallengeHeaderLen = 48;
158 static constexpr size_t kResponseLenV1 = 24;
159 static constexpr size_t kChallengeLen = 8;
160 static constexpr size_t kVersionFieldLen = 8;
161 static constexpr size_t kNtlmHashLen = 16;
162 static constexpr size_t kNtlmProofLenV2 = kNtlmHashLen;
163 static constexpr size_t kSessionKeyLenV2 = kNtlmHashLen;
164 static constexpr size_t kMicLenV2 = kNtlmHashLen;
165 static constexpr size_t kChannelBindingsHashLen = kNtlmHashLen;
166 static constexpr size_t kEpaUnhashedStructHeaderLen = 20;
167 static constexpr size_t kProofInputLenV2 = 28;
168 static constexpr size_t kAvPairHeaderLen = 2 * sizeof(uint16_t);
169 static constexpr size_t kNtlmResponseHeaderLenV2 =
170     kNtlmProofLenV2 + kProofInputLenV2;
171 static constexpr size_t kAuthenticateHeaderLenV1 = 64;
172 static constexpr size_t kMicOffsetV2 = 72;
173 static constexpr size_t kAuthenticateHeaderLenV2 = 88;
174 
175 static constexpr size_t kMaxFqdnLen = 255;
176 static constexpr size_t kMaxUsernameLen = 104;
177 static constexpr size_t kMaxPasswordLen = 256;
178 
179 static constexpr NegotiateFlags kNegotiateMessageFlags =
180     NegotiateFlags::kUnicode | NegotiateFlags::kOem |
181     NegotiateFlags::kRequestTarget | NegotiateFlags::kNtlm |
182     NegotiateFlags::kAlwaysSign | NegotiateFlags::kExtendedSessionSecurity;
183 
184 }  // namespace net::ntlm
185 
186 #endif  // NET_NTLM_NTLM_CONSTANTS_H_
187