OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 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/http/ntlm_message.h" | |
16 | |
17 namespace net { | |
18 | |
19 // Supports various bounds checked low level buffer | |
20 // operations required by an NTLM implementation. | |
21 // | |
22 // The class supports sequential read of a provided | |
23 // buffer. All reads perform bounds checking to ensure | |
24 // enough space is remaining in the buffer. | |
25 // | |
26 // | |
27 // Read* methods read from the buffer at the current cursor | |
28 // position and perform any necessary type conversion and | |
29 // provide the data in out params. After a successful read | |
30 // the cursor position is advanced past the read field. | |
31 // | |
32 // Failed reads leave the internal cursor at the same | |
33 // position as before the call. | |
34 // | |
35 // | |
36 // Read*Payload methods first read a security buffer see | |
37 // |ReadSecurityBuffer| then read the requested payload | |
38 // from the offset and length stated in the security buffer. | |
39 // | |
40 // If the length and offset in the security buffer would | |
41 // cause a read outside the message buffer the payload will | |
42 // not be read and the function will return false. | |
43 // | |
44 // The cursor will remain as it was before the call as if | |
45 // the security buffer had not been read. | |
46 // | |
47 // | |
48 // Skip* methods skip the cursor over that same number | |
49 // of bytes that the equivalent Read method would without | |
50 // reading or returning the values. | |
51 // | |
52 // | |
53 // Match* methods are used to validate fields in the | |
54 // buffer that should have expected values, such as | |
55 // signatures or message identifiers. | |
Ryan Sleevi
2017/05/30 19:02:22
I can't tell - are these aligned to the maximal us
zentaro
2017/06/05 17:28:44
Done.
| |
56 // | |
57 // | |
58 // Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication | |
59 // Protocol specification version 28.0 [1] | |
60 // | |
61 // [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx | |
62 class NET_EXPORT NtlmBufferReader { | |
63 public: | |
64 NtlmBufferReader(const base::StringPiece buffer); | |
Ryan Sleevi
2017/05/30 19:02:22
style: you can drop the const since you're passing
Ryan Sleevi
2017/05/30 19:02:22
style: "explicit" - https://google.github.io/style
zentaro
2017/06/05 17:28:44
Done. I previously was passing by const-ref then s
zentaro
2017/06/05 17:28:44
Done.
| |
65 NtlmBufferReader(const uint8_t* ptr, size_t len); | |
Ryan Sleevi
2017/05/30 19:02:22
Since you accept a base::StringPiece, is this over
zentaro
2017/06/05 17:28:44
I could I guess try and convert all the callers to
| |
66 ~NtlmBufferReader(); | |
67 | |
68 size_t GetLength() const { return buffer_.length(); } | |
69 size_t GetCursor() const { return cursor_; } | |
70 bool IsEndOfBuffer() const { return cursor_ >= GetLength(); } | |
71 | |
72 const uint8_t* GetBufferPtr() const { | |
73 return reinterpret_cast<const uint8_t*>(buffer_.data()); | |
74 } | |
75 | |
76 // Returns a pointer to the underlying buffer at the current cursor | |
77 // position. | |
78 const uint8_t* GetBufferAtCursor() const { return GetBufferPtr() + cursor_; } | |
Ryan Sleevi
2017/05/30 19:02:22
Both this and the function on line 72 seem like th
zentaro
2017/06/05 17:28:44
I managed to refactor out all the public uses of t
| |
79 | |
80 // Returns true if there are |len| more bytes between the | |
81 // current cursor position and the end of the buffer. | |
82 bool CanRead(size_t len) const; | |
83 | |
84 // Returns true if there are |len| more bytes between |offset| | |
85 // and the end of the buffer. The cursor position is not used | |
86 // or modified. | |
87 bool CanReadFrom(size_t offset, size_t len) const; | |
88 | |
89 bool ReadUInt16(uint16_t* value); | |
Ryan Sleevi
2017/05/30 19:02:22
Document a bit more - for example, what's the endi
zentaro
2017/06/05 17:28:44
Done.
| |
90 bool ReadUInt32(uint32_t* value); | |
91 bool ReadUInt64(uint64_t* value); | |
92 | |
93 bool ReadBytes(uint8_t* buffer, size_t len); | |
94 | |
95 // A security buffer is an 8 byte structure that defines the | |
96 // offset and length of a payload (string, struct or byte array) | |
97 // that appears after the fixed part of the message. | |
98 // | |
99 // The structure is (little endian fields): | |
100 // uint16 - |length| Length of payload | |
101 // uint16 - Allocation (this is always ignored and not returned) | |
102 // uint32 - |offset| Offset from start of message | |
103 bool ReadSecurityBuffer(uint16_t* length, uint32_t* offset); | |
104 | |
105 bool ReadAsciiString(std::string* value, size_t len); | |
106 bool ReadUnicodeString(base::string16* value, size_t len); | |
Ryan Sleevi
2017/05/30 19:02:22
I suspect you're borrowing from the NTLM language,
| |
107 | |
108 // There are 3 message types Negotiate (sent by client), | |
109 // Challenge (sent by server), and Authenticate (sent by client). | |
110 // | |
111 // This reads the message type from the header and will return | |
112 // false if the value is invalid. | |
113 bool ReadMessageType(NtlmMessage::MessageType* message_type); | |
114 | |
115 bool ReadAsciiPayload(std::string* value); | |
116 bool ReadUnicodePayload(base::string16* value); | |
117 bool ReadBytesPayload(uint8_t* buffer, size_t buffer_len); | |
Ryan Sleevi
2017/05/30 19:02:22
How are the *Payload functions different from the
zentaro
2017/06/05 17:28:44
Added some additional docs to clarify. But the 'pa
| |
118 | |
119 bool SkipSecurityBuffer(); | |
120 | |
121 // Skips over the security buffer without returning the values | |
Ryan Sleevi
2017/05/30 19:02:22
grammar: "returning the values, " (add a comma)
zentaro
2017/06/05 17:28:44
Done.
| |
122 // but fails if the values would cause a read outside the buffer | |
123 // if the payload was actually read. | |
124 bool SkipSecurityBufferWithValidation(); | |
125 | |
126 // Skips over |count| bytes in the buffer. Returns false if there | |
127 // is not |count| bytes left in the buffer. | |
128 bool SkipBytes(size_t count); | |
129 | |
130 // Reads and returns true if the next 8 bytes matches the signature in | |
131 // an NTLM message "NTLMSSP\0" | |
132 bool MatchSignature(); | |
133 | |
134 // Reads the message type from the cursor and returns true | |
135 // if it is |message_type|. | |
136 bool MatchMessageType(NtlmMessage::MessageType message_type); | |
137 | |
138 // Performs |MatchSignature| then |MatchMessageType|. | |
139 bool MatchMessageHeader(NtlmMessage::MessageType message_type); | |
140 | |
141 // Reads and returns true if there are |count| bytes of zeros. | |
142 bool MatchZeros(size_t count); | |
143 | |
144 // Reads and returns true if the next 8 bytes contain an empty | |
145 // ie. all zero security buffer. | |
146 bool MatchEmptySecurityBuffer(); | |
147 | |
148 private: | |
149 // Reads |sizeof(T)| bytes of an integer type from a little-endian | |
150 // buffer. | |
151 template <typename T> | |
152 bool ReadUInt(T* value); | |
153 | |
154 // Sets the cursor position. This is used when reading payloads to | |
155 // move the cursor to the start of the payload indicated by the | |
156 // security buffer. | |
157 bool SetCursor(size_t cursor); | |
158 | |
159 uint8_t GetByteAtCursor() const { | |
160 DCHECK(!IsEndOfBuffer()); | |
161 return *(GetBufferAtCursor()); | |
162 } | |
163 | |
164 const base::StringPiece buffer_; | |
165 size_t cursor_; | |
166 | |
167 DISALLOW_COPY_AND_ASSIGN(NtlmBufferReader); | |
168 }; | |
169 | |
170 } // namespace net | |
171 | |
172 #endif // NET_BASE_NTLM_BUFFER_READER_H_ | |
OLD | NEW |