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