Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: net/ntlm/ntlm_buffer_reader.h

Issue 2879353002: Add a buffer reader/writer for NTLM. (Closed)
Patch Set: Add a buffer reader/writer for NTLM. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698