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 #include "net/http/ntlm_buffer_writer.h" | |
6 | |
7 #include <string.h> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/strings/sys_string_conversions.h" | |
11 #include "base/strings/utf_string_conversions.h" | |
12 | |
13 #if defined(ARCH_CPU_LITTLE_ENDIAN) | |
14 #define IS_LITTLE_ENDIAN 1 | |
15 #undef IS_BIG_ENDIAN | |
16 #elif defined(ARCH_CPU_BIG_ENDIAN) | |
17 #define IS_BIG_ENDIAN 1 | |
18 #undef IS_LITTLE_ENDIAN | |
19 #else | |
20 #error "Unknown endianness" | |
21 #endif | |
22 | |
23 namespace net { | |
24 | |
25 NtlmBufferWriter::NtlmBufferWriter(size_t buffer_len) | |
26 : buffer_len_(buffer_len), cursor_(0) { | |
27 buffer_.reset(new uint8_t[buffer_len]); | |
28 } | |
29 | |
30 NtlmBufferWriter::~NtlmBufferWriter() {} | |
31 | |
32 bool NtlmBufferWriter::CanWrite(size_t len) const { | |
33 if (GetBufferPtr() == nullptr) | |
Ryan Sleevi
2017/06/08 18:36:34
if (!GetBufferPtr())
return false;
?
zentaro
2017/06/12 23:12:07
Done.
| |
34 return false; | |
35 | |
36 DCHECK(cursor_ <= GetLength()); | |
Ryan Sleevi
2017/06/08 18:36:34
DCHECK_LE(cursor_, GetLength());
zentaro
2017/06/12 23:12:07
Done.
| |
37 | |
38 if (len == 0) | |
39 return true; | |
40 | |
41 return (cursor_ + len > cursor_) && (cursor_ + len <= GetLength()); | |
Ryan Sleevi
2017/06/08 18:36:34
len <= GetLength() && cursor_ <= GetLength() - len
zentaro
2017/06/12 23:12:07
Done.
| |
42 } | |
43 | |
44 bool NtlmBufferWriter::SetCursor(size_t cursor) { | |
45 if ((GetBufferPtr() == nullptr) || (cursor > GetLength())) | |
Ryan Sleevi
2017/06/08 18:36:34
if (!GetBufferPtr() || (cursor > GetLength()))
zentaro
2017/06/12 23:12:07
Done.
| |
46 return false; | |
47 | |
48 cursor_ = cursor; | |
49 return true; | |
50 } | |
51 | |
52 bool NtlmBufferWriter::WriteUInt64(uint64_t value) { | |
53 return WriteUInt<uint64_t>(value); | |
54 } | |
55 bool NtlmBufferWriter::WriteUInt32(uint32_t value) { | |
56 return WriteUInt<uint32_t>(value); | |
57 } | |
58 bool NtlmBufferWriter::WriteUInt16(uint16_t value) { | |
59 return WriteUInt<uint16_t>(value); | |
60 } | |
61 | |
62 template <typename T> | |
63 bool NtlmBufferWriter::WriteUInt(T value) { | |
64 size_t int_size = sizeof(T); | |
65 if (!CanWrite(int_size)) | |
66 return false; | |
67 | |
68 for (size_t i = 0; i < int_size; i++) { | |
69 GetBufferPtr()[cursor_++] = static_cast<uint8_t>(value & 0xff); | |
70 value >>= 8; | |
71 } | |
72 | |
73 return true; | |
74 } | |
75 | |
76 bool NtlmBufferWriter::WriteBytes(const uint8_t* buffer, size_t len) { | |
77 if (!CanWrite(len)) | |
78 return false; | |
79 | |
80 memcpy(reinterpret_cast<void*>(GetBufferPtr() + cursor_), | |
81 reinterpret_cast<const void*>(buffer), len); | |
82 | |
83 cursor_ += len; | |
84 return true; | |
85 } | |
86 | |
87 bool NtlmBufferWriter::WriteBytes(base::StringPiece bytes) { | |
88 return WriteBytes(reinterpret_cast<const uint8_t*>(bytes.data()), | |
89 bytes.length()); | |
90 } | |
91 | |
92 bool NtlmBufferWriter::WriteSecurityBuffer(ntlm::SecurityBuffer sec_buf) { | |
93 if (!CanWrite(ntlm::SECURITY_BUFFER_LEN)) | |
94 return false; | |
95 | |
96 if (WriteUInt16(sec_buf.length) && WriteUInt16(sec_buf.length) && | |
asanka
2017/06/08 19:40:09
Nit: if (X) return true; return false ---> return
zentaro
2017/06/12 23:12:07
I wrote it like that so I do NOTREACHED() but I re
| |
97 WriteUInt32(sec_buf.offset)) | |
98 return true; | |
99 | |
100 NOTREACHED(); | |
101 return false; | |
102 } | |
103 | |
104 bool NtlmBufferWriter::WriteEmptySecurityBuffer() { | |
105 return WriteSecurityBuffer(ntlm::SecurityBuffer()); | |
106 } | |
107 | |
108 bool NtlmBufferWriter::WriteNarrowString(const std::string& str) { | |
asanka
2017/06/08 19:40:09
Nit: Rewrite this using WriteBytes()
zentaro
2017/06/12 23:12:07
Done.
| |
109 if (!CanWrite(str.length())) | |
110 return false; | |
111 | |
112 memcpy(reinterpret_cast<void*>(GetBufferPtr() + cursor_), str.c_str(), | |
113 str.length()); | |
114 cursor_ += str.length(); | |
115 return true; | |
116 } | |
117 | |
118 bool NtlmBufferWriter::WriteString16AsUTF8(const base::string16& str) { | |
119 // In practice this converts it to UTF8. | |
120 std::string utf8 = base::SysWideToNativeMB(base::UTF16ToWide(str)); | |
asanka
2017/06/08 19:40:09
Why not Utf16ToUtf8()? That way the behavior won't
zentaro
2017/06/12 23:12:07
Done.
| |
121 return WriteNarrowString(utf8); | |
122 } | |
123 | |
124 bool NtlmBufferWriter::WriteUnicodeString(const base::string16& str) { | |
125 size_t num_bytes = str.length() * 2; | |
126 if (!CanWrite(num_bytes)) | |
127 return false; | |
128 | |
129 #if IS_BIG_ENDIAN | |
130 uint8_t* ptr = reinterpret_cast<uint8_t*>(GetBufferPtr() + cursor_); | |
131 | |
132 for (int i = 0; i < num_bytes; i += 2) { | |
133 ptr[i] = str[i / 2] % 0xff; | |
134 ptr[i + 1] = str[i / 2] >> 8; | |
135 } | |
136 #else | |
137 memcpy(reinterpret_cast<void*>(GetBufferPtr() + cursor_), str.c_str(), | |
138 num_bytes); | |
139 | |
140 #endif | |
141 | |
142 cursor_ += num_bytes; | |
143 return true; | |
144 } | |
145 | |
146 bool NtlmBufferWriter::WriteNarrowStringAsString16(const std::string& str) { | |
147 base::string16 unicode; | |
148 unicode.assign(str.begin(), str.end()); | |
asanka
2017/06/08 19:40:09
not the same as Utf8ToUtf16.
zentaro
2017/06/12 23:12:07
Done.
| |
149 return WriteUnicodeString(unicode); | |
150 } | |
151 | |
152 bool NtlmBufferWriter::WriteSignature() { | |
153 return WriteBytes(ntlm::SIGNATURE, ntlm::SIGNATURE_LEN); | |
154 } | |
155 | |
156 bool NtlmBufferWriter::WriteZeros(size_t count) { | |
157 if (!CanWrite(count)) | |
158 return false; | |
159 | |
160 memset(GetBufferPtr() + cursor_, 0, count); | |
161 cursor_ += count; | |
162 return true; | |
163 } | |
164 | |
165 bool NtlmBufferWriter::WriteMessageType(ntlm::MessageType message_type) { | |
166 return WriteUInt32(message_type); | |
167 } | |
168 | |
169 bool NtlmBufferWriter::WriteMessageHeader(ntlm::MessageType message_type) { | |
170 if (!CanWrite(ntlm::SIGNATURE_LEN + sizeof(uint32_t))) | |
171 return false; | |
172 | |
173 if (WriteSignature() && WriteMessageType(message_type)) | |
174 return true; | |
175 | |
176 NOTREACHED(); | |
177 return false; | |
178 } | |
179 | |
180 // static | |
181 size_t NtlmBufferWriter::GetStringPayloadLength(const base::string16& str, | |
182 bool is_unicode) { | |
183 if (is_unicode) | |
184 return str.length() * 2; | |
185 | |
186 // When |WriteString16AsUTF8| is called with a |base::string16|, the string | |
187 // is effectively converted to UTF8 by |base::SysWideToNativeMB|. | |
188 // Do the conversion to ensure that the character count is correct. | |
189 return base::SysWideToNativeMB(base::UTF16ToWide(str)).length(); | |
asanka
2017/06/08 19:40:09
Utf16ToUtf8().
zentaro
2017/06/12 23:12:07
Done.
| |
190 } | |
191 | |
192 // static | |
193 size_t NtlmBufferWriter::GetStringPayloadLength(const std::string& str, | |
194 bool is_unicode) { | |
195 // When |WriteUnicodePayload| is called with a |std::string| | |
196 // the string is assumed ASCII and the characters are zero-padded. | |
asanka
2017/06/08 19:40:09
Seems a bit inconsistent whether input strings are
zentaro
2017/06/12 23:12:07
Per our offline discussion regarding the 8 bit ver
| |
197 return is_unicode ? str.length() * 2 : str.length(); | |
198 } | |
199 | |
200 } // namespace net | |
OLD | NEW |