Chromium Code Reviews| 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 |