OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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 #ifndef NET_BASE_NTLM_BUFFER_READER_H_ | |
6 #define NET_BASE_NTLM_BUFFER_READER_H_ | |
7 | |
8 #include <stddef.h> | |
9 #include <stdint.h> | |
10 | |
11 #include <string> | |
12 | |
13 #include "base/strings/string_piece.h" | |
14 #include "net/base/net_export.h" | |
15 #include "net/ntlm/ntlm_constants.h" | |
16 | |
17 namespace net { | |
18 namespace ntlm { | |
19 | |
20 // Supports various bounds-checked low level buffer operations required by an | |
21 // NTLM implementation. | |
22 // | |
23 // The class supports sequential read of a provided buffer. All reads perform | |
Ryan Sleevi
2017/07/10 15:07:56
s/supports sequential/supports the sequential/
Al
zentaro
2017/07/11 14:00:29
Done.
| |
24 // bounds checking to ensure enough space is remaining in the buffer. | |
25 // | |
26 // Read* methods read from the buffer at the current cursor position and | |
27 // perform any necessary type conversion and provide the data in out params. | |
28 // After a successful read the cursor position is advanced past the read | |
29 // field. | |
30 // | |
31 // Failed Read*s or Match*s leave the cursor in an undefined position and the | |
32 // buffer MUST be discarded with no further operations performed. | |
33 // | |
34 // Read*Payload methods first reads a security buffer (see | |
35 // |ReadSecurityBuffer|), then reads the requested payload from the offset | |
36 // and length stated in the security buffer. | |
37 // | |
38 // If the length and offset in the security buffer would cause a read outside | |
39 // the message buffer the payload will not be read and the function will | |
40 // return false. | |
41 // | |
42 // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication Protocol | |
43 // Specification version 28.0 [1]. Additional NTLM reference [2]. | |
44 // | |
45 // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx | |
46 // [2] http://davenport.sourceforge.net/ntlm.html | |
47 class NET_EXPORT_PRIVATE NtlmBufferReader { | |
48 public: | |
49 explicit NtlmBufferReader(base::StringPiece buffer); | |
50 | |
51 // This class does not take ownership of |ptr| so the caller must ensure | |
Ryan Sleevi
2017/07/10 15:07:56
s/|ptr| so/|ptr|, so/
zentaro
2017/07/11 14:00:29
Done.
| |
52 // that the buffer outlives the |NtlmBufferReader|. | |
53 NtlmBufferReader(const uint8_t* ptr, size_t len); | |
54 ~NtlmBufferReader(); | |
55 | |
56 size_t GetLength() const { return buffer_.length(); } | |
57 size_t GetCursor() const { return cursor_; } | |
58 bool IsEndOfBuffer() const { return cursor_ >= GetLength(); } | |
59 | |
60 // Returns true if there are |len| more bytes between the current cursor | |
61 // position and the end of the buffer. | |
62 bool CanRead(size_t len) const; | |
63 | |
64 // Returns true if there are |len| more bytes between |offset| and the end | |
65 // of the buffer. The cursor position is not used or modified. | |
66 bool CanReadFrom(size_t offset, size_t len) const; | |
67 | |
68 // Returns true if it would be possible to read the payload described by the | |
69 // security buffer. | |
70 bool CanReadFrom(SecurityBuffer sec_buf) const { | |
71 return CanReadFrom(sec_buf.offset, sec_buf.length); | |
72 } | |
73 | |
74 // Reads a 16 bit value (little endian) as a uint16_t. If there are not 16 | |
75 // more bits available it returns false. | |
Ryan Sleevi
2017/07/10 15:07:56
s/available it/available, it/
zentaro
2017/07/11 14:00:29
Done.
| |
76 bool ReadUInt16(uint16_t* value) WARN_UNUSED_RESULT; | |
77 | |
78 // Reads a 32 bit value (little endian) as a uint32_t. If there are not 32 | |
79 // more bits available it returns false. | |
Ryan Sleevi
2017/07/10 15:07:56
s/available it/available, it/
zentaro
2017/07/11 14:00:29
Done.
| |
80 bool ReadUInt32(uint32_t* value) WARN_UNUSED_RESULT; | |
81 | |
82 // Reads a 64 bit value (little endian) as a uint64_t. If there are not 64 | |
83 // more bits available it returns false. | |
Ryan Sleevi
2017/07/10 15:07:56
s/available it/available, it/
zentaro
2017/07/11 14:00:29
Done.
| |
84 bool ReadUInt64(uint64_t* value) WARN_UNUSED_RESULT; | |
85 | |
86 // Calls |ReadUInt32| and returns it cast as |NegotiateFlags|. No | |
87 // validation of the value takes place. | |
88 bool ReadFlags(NegotiateFlags* flags) WARN_UNUSED_RESULT; | |
89 | |
90 // Reads |len| bytes and copies them into |buffer|. | |
91 bool ReadBytes(uint8_t* buffer, size_t len) WARN_UNUSED_RESULT; | |
92 | |
93 // Reads |sec_buf.length| bytes from offset |sec_buf.offset| and copies them | |
94 // into |buffer|. If the security buffer specifies a payload outside the | |
95 // buffer then the call fails. | |
Ryan Sleevi
2017/07/10 15:07:56
s/buffer then/buffer, then/
zentaro
2017/07/11 14:00:29
Done.
| |
96 bool ReadBytesFrom(const SecurityBuffer& sec_buf, | |
asanka
2017/07/11 15:19:16
Should note that this method doesn't affect the cu
zentaro
2017/07/11 20:19:53
Done.
| |
97 uint8_t* buffer) WARN_UNUSED_RESULT; | |
98 | |
99 // A security buffer is an 8 byte structure that defines the offset and | |
100 // length of a payload (string, struct or byte array) that appears after the | |
101 // fixed part of the message. | |
102 // | |
103 // The structure is (little endian fields): | |
104 // uint16 - |length| Length of payload | |
105 // uint16 - Allocation (this is always ignored and not returned) | |
106 // uint32 - |offset| Offset from start of message | |
107 bool ReadSecurityBuffer(SecurityBuffer* sec_buf) WARN_UNUSED_RESULT; | |
108 | |
109 // There are 3 message types Negotiate (sent by client), Challenge (sent by | |
110 // server), and Authenticate (sent by client). | |
111 // | |
112 // This reads the message type from the header and will return false if the | |
113 // value is invalid. | |
114 bool ReadMessageType(MessageType* message_type) WARN_UNUSED_RESULT; | |
115 | |
116 // Skips over a security buffer field without reading the fields. This is | |
117 // the equivalent of advancing the cursor 8 bytes. Returns false if there | |
118 // are less than 8 bytes left in the buffer. | |
119 bool SkipSecurityBuffer() WARN_UNUSED_RESULT; | |
120 | |
121 // Skips over the security buffer without returning the values, but fails if | |
122 // the values would cause a read outside the buffer if the payload was | |
123 // actually read. | |
124 bool SkipSecurityBufferWithValidation() WARN_UNUSED_RESULT; | |
125 | |
126 // Skips over |count| bytes in the buffer. Returns false if there is not | |
Ryan Sleevi
2017/07/10 15:07:56
s/is not/are not/ (subject/verb agreement with plu
zentaro
2017/07/11 14:00:29
Done.
| |
127 // |count| bytes left in the buffer. | |
128 bool SkipBytes(size_t count) WARN_UNUSED_RESULT; | |
129 | |
130 // Reads and returns true if the next 8 bytes matches the signature in an | |
131 // NTLM message "NTLMSSP\0". The cursor advances if the the signature | |
132 // is matched. | |
133 bool MatchSignature() WARN_UNUSED_RESULT; | |
134 | |
135 // Performs |ReadMessageType| and returns true if the value is | |
136 // |message_type|. If the read fails or the message type does not match, | |
137 // the buffer is invalid and MUST be discarded. | |
138 bool MatchMessageType(MessageType message_type) WARN_UNUSED_RESULT; | |
139 | |
140 // Performs |MatchSignature| then |MatchMessageType|. | |
141 bool MatchMessageHeader(MessageType message_type) WARN_UNUSED_RESULT; | |
142 | |
143 // Performs |ReadBytes(count)| and returns true if the contents is all | |
144 // zero. | |
145 bool MatchZeros(size_t count) WARN_UNUSED_RESULT; | |
146 | |
147 // Reads the security buffer and returns true if the length is 0 and | |
148 // the offset is within the message. On failure the buffer is invalid | |
Ryan Sleevi
2017/07/10 15:07:56
s/failure the/failure, the/
zentaro
2017/07/11 14:00:29
Done.
| |
149 // and MUST be discarded. | |
150 bool MatchEmptySecurityBuffer() WARN_UNUSED_RESULT; | |
151 | |
152 private: | |
153 // Reads |sizeof(T)| bytes of an integer type from a little-endian buffer. | |
154 template <typename T> | |
155 bool ReadUInt(T* value); | |
156 | |
157 // Sets the cursor position. This is used when reading payloads to move the | |
158 // cursor to the start of the payload indicated by the security buffer. | |
Ryan Sleevi
2017/07/10 15:07:56
comment nit: You're describing how this is used (a
zentaro
2017/07/11 14:00:29
Acknowledged.
asanka
2017/07/11 15:19:16
I'd be okay with leaving out the "this is used whe
zentaro
2017/07/11 20:19:53
Removed the "this is used" because we removed all
| |
159 // The caller should use |GetLength|, |CanRead|, or |CanReadFrom| to verify | |
160 // the bounds before calling this method. | |
161 void SetCursor(size_t cursor); | |
162 | |
163 // Advances the cursor by |count| bytes. The caller should use |GetLength|, | |
164 // |CanRead|, or |CanReadFrom| to verify the bounds before calling this | |
165 // method. | |
166 void AdvanceCursor(size_t count) { SetCursor(GetCursor() + count); } | |
167 | |
168 // Returns a constant pointer to the start of the buffer. | |
169 const uint8_t* GetBufferPtr() const { | |
170 return reinterpret_cast<const uint8_t*>(buffer_.data()); | |
171 } | |
172 | |
173 // Returns a pointer to the underlying buffer at the current cursor | |
174 // position. | |
175 const uint8_t* GetBufferAtCursor() const { return GetBufferPtr() + cursor_; } | |
176 | |
177 // Returns the byte at the current cursor position. | |
178 uint8_t GetByteAtCursor() const { | |
179 DCHECK(!IsEndOfBuffer()); | |
180 return *(GetBufferAtCursor()); | |
181 } | |
182 | |
183 const base::StringPiece buffer_; | |
184 size_t cursor_; | |
185 | |
186 DISALLOW_COPY_AND_ASSIGN(NtlmBufferReader); | |
187 }; | |
188 | |
189 } // namespace ntlm | |
190 } // namespace net | |
191 | |
192 #endif // NET_BASE_NTLM_BUFFER_READER_H_ | |
OLD | NEW |