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

Unified Diff: net/http/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, 7 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 side-by-side diff with in-line comments
Download patch
Index: net/http/ntlm_buffer_reader.h
diff --git a/net/http/ntlm_buffer_reader.h b/net/http/ntlm_buffer_reader.h
new file mode 100644
index 0000000000000000000000000000000000000000..3c30e91e4a0724bcd767971de0441d1fa9d3ee06
--- /dev/null
+++ b/net/http/ntlm_buffer_reader.h
@@ -0,0 +1,172 @@
+// Copyright (c) 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_BASE_NTLM_BUFFER_READER_H_
+#define NET_BASE_NTLM_BUFFER_READER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "net/base/net_export.h"
+#include "net/http/ntlm_message.h"
+
+namespace net {
+
+// Supports various bounds checked low level buffer
+// operations required by an NTLM implementation.
+//
+// The class supports sequential read of a provided
+// buffer. All reads perform bounds checking to ensure
+// enough space is remaining in the buffer.
+//
+//
+// Read* methods read from the buffer at the current cursor
+// position and perform any necessary type conversion and
+// provide the data in out params. After a successful read
+// the cursor position is advanced past the read field.
+//
+// Failed reads leave the internal cursor at the same
+// position as before the call.
+//
+//
+// Read*Payload methods first read a security buffer see
+// |ReadSecurityBuffer| then read the requested payload
+// from the offset and length stated in the security buffer.
+//
+// If the length and offset in the security buffer would
+// cause a read outside the message buffer the payload will
+// not be read and the function will return false.
+//
+// The cursor will remain as it was before the call as if
+// the security buffer had not been read.
+//
+//
+// Skip* methods skip the cursor over that same number
+// of bytes that the equivalent Read method would without
+// reading or returning the values.
+//
+//
+// Match* methods are used to validate fields in the
+// buffer that should have expected values, such as
+// 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.
+//
+//
+// Based on [MS-NLMP]: NT LAN Manager (NTLM) Authentication
+// Protocol specification version 28.0 [1]
+//
+// [1] https://msdn.microsoft.com/en-us/library/cc236621.aspx
+class NET_EXPORT NtlmBufferReader {
+ public:
+ 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.
+ 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
+ ~NtlmBufferReader();
+
+ size_t GetLength() const { return buffer_.length(); }
+ size_t GetCursor() const { return cursor_; }
+ bool IsEndOfBuffer() const { return cursor_ >= GetLength(); }
+
+ const uint8_t* GetBufferPtr() const {
+ return reinterpret_cast<const uint8_t*>(buffer_.data());
+ }
+
+ // Returns a pointer to the underlying buffer at the current cursor
+ // position.
+ 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
+
+ // Returns true if there are |len| more bytes between the
+ // current cursor position and the end of the buffer.
+ bool CanRead(size_t len) const;
+
+ // Returns true if there are |len| more bytes between |offset|
+ // and the end of the buffer. The cursor position is not used
+ // or modified.
+ bool CanReadFrom(size_t offset, size_t len) const;
+
+ 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.
+ bool ReadUInt32(uint32_t* value);
+ bool ReadUInt64(uint64_t* value);
+
+ bool ReadBytes(uint8_t* buffer, size_t len);
+
+ // A security buffer is an 8 byte structure that defines the
+ // offset and length of a payload (string, struct or byte array)
+ // that appears after the fixed part of the message.
+ //
+ // The structure is (little endian fields):
+ // uint16 - |length| Length of payload
+ // uint16 - Allocation (this is always ignored and not returned)
+ // uint32 - |offset| Offset from start of message
+ bool ReadSecurityBuffer(uint16_t* length, uint32_t* offset);
+
+ bool ReadAsciiString(std::string* value, size_t len);
+ 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,
+
+ // There are 3 message types Negotiate (sent by client),
+ // Challenge (sent by server), and Authenticate (sent by client).
+ //
+ // This reads the message type from the header and will return
+ // false if the value is invalid.
+ bool ReadMessageType(NtlmMessage::MessageType* message_type);
+
+ bool ReadAsciiPayload(std::string* value);
+ bool ReadUnicodePayload(base::string16* value);
+ 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
+
+ bool SkipSecurityBuffer();
+
+ // 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.
+ // but fails if the values would cause a read outside the buffer
+ // if the payload was actually read.
+ bool SkipSecurityBufferWithValidation();
+
+ // Skips over |count| bytes in the buffer. Returns false if there
+ // is not |count| bytes left in the buffer.
+ bool SkipBytes(size_t count);
+
+ // Reads and returns true if the next 8 bytes matches the signature in
+ // an NTLM message "NTLMSSP\0"
+ bool MatchSignature();
+
+ // Reads the message type from the cursor and returns true
+ // if it is |message_type|.
+ bool MatchMessageType(NtlmMessage::MessageType message_type);
+
+ // Performs |MatchSignature| then |MatchMessageType|.
+ bool MatchMessageHeader(NtlmMessage::MessageType message_type);
+
+ // Reads and returns true if there are |count| bytes of zeros.
+ bool MatchZeros(size_t count);
+
+ // Reads and returns true if the next 8 bytes contain an empty
+ // ie. all zero security buffer.
+ bool MatchEmptySecurityBuffer();
+
+ private:
+ // Reads |sizeof(T)| bytes of an integer type from a little-endian
+ // buffer.
+ template <typename T>
+ bool ReadUInt(T* value);
+
+ // Sets the cursor position. This is used when reading payloads to
+ // move the cursor to the start of the payload indicated by the
+ // security buffer.
+ bool SetCursor(size_t cursor);
+
+ uint8_t GetByteAtCursor() const {
+ DCHECK(!IsEndOfBuffer());
+ return *(GetBufferAtCursor());
+ }
+
+ const base::StringPiece buffer_;
+ size_t cursor_;
+
+ DISALLOW_COPY_AND_ASSIGN(NtlmBufferReader);
+};
+
+} // namespace net
+
+#endif // NET_BASE_NTLM_BUFFER_READER_H_
« no previous file with comments | « net/BUILD.gn ('k') | net/http/ntlm_buffer_reader.cc » ('j') | net/http/ntlm_buffer_reader.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698