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) |
| 34 return false; |
| 35 |
| 36 DCHECK(cursor_ <= GetLength()); |
| 37 |
| 38 if (len == 0) |
| 39 return true; |
| 40 |
| 41 return (cursor_ + len > cursor_) && (cursor_ + len <= GetLength()); |
| 42 } |
| 43 |
| 44 bool NtlmBufferWriter::SetCursor(size_t cursor) { |
| 45 if ((GetBufferPtr() == nullptr) || (cursor > GetLength())) |
| 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::WriteSecurityBuffer(uint16_t length, uint32_t offset) { |
| 88 if (!CanWrite(NtlmMessage::SECURITY_BUFFER_LEN)) |
| 89 return false; |
| 90 |
| 91 if (WriteUInt16(length) && WriteUInt16(length) && WriteUInt32(offset)) |
| 92 return true; |
| 93 |
| 94 NOTREACHED(); |
| 95 return false; |
| 96 } |
| 97 |
| 98 bool NtlmBufferWriter::WriteEmptySecurityBuffer() { |
| 99 return WriteSecurityBuffer(0, 0); |
| 100 } |
| 101 |
| 102 bool NtlmBufferWriter::WriteNarrowString(const std::string& str) { |
| 103 if (!CanWrite(str.length())) |
| 104 return false; |
| 105 |
| 106 memcpy(reinterpret_cast<void*>(GetBufferPtr() + cursor_), str.c_str(), |
| 107 str.length()); |
| 108 cursor_ += str.length(); |
| 109 return true; |
| 110 } |
| 111 |
| 112 bool NtlmBufferWriter::WriteString16AsUTF8(const base::string16& str) { |
| 113 // In practice this converts it to UTF8. |
| 114 std::string utf8 = base::SysWideToNativeMB(base::UTF16ToWide(str)); |
| 115 return WriteNarrowString(utf8); |
| 116 } |
| 117 |
| 118 bool NtlmBufferWriter::WriteUnicodeString(const base::string16& str) { |
| 119 size_t num_bytes = str.length() * 2; |
| 120 if (!CanWrite(num_bytes)) |
| 121 return false; |
| 122 |
| 123 if (!WriteUnicodeStringIntoBuffer(str, GetBufferPtr() + cursor_, num_bytes)) |
| 124 return false; |
| 125 |
| 126 cursor_ += num_bytes; |
| 127 return true; |
| 128 } |
| 129 |
| 130 bool NtlmBufferWriter::WriteNarrowStringAsString16(const std::string& str) { |
| 131 base::string16 unicode; |
| 132 unicode.assign(str.begin(), str.end()); |
| 133 return WriteUnicodeString(unicode); |
| 134 } |
| 135 |
| 136 bool NtlmBufferWriter::WriteUnicodeStringIntoBuffer(const base::string16& str, |
| 137 uint8_t* buffer, |
| 138 size_t buffer_len) { |
| 139 // TODO: static?? |
| 140 size_t num_bytes = str.length() * 2; |
| 141 if (num_bytes > buffer_len) |
| 142 return false; |
| 143 |
| 144 #if IS_BIG_ENDIAN |
| 145 uint8_t* ptr = reinterpret_cast<uint8_t*>(GetBufferPtr() + cursor_); |
| 146 |
| 147 for (int i = 0; i < num_bytes; i += 2) { |
| 148 ptr[i] = str[i / 2] % 0xff; |
| 149 ptr[i + 1] = str[i / 2] >> 8; |
| 150 } |
| 151 #else |
| 152 memcpy(reinterpret_cast<void*>(GetBufferPtr() + cursor_), str.c_str(), |
| 153 num_bytes); |
| 154 |
| 155 #endif |
| 156 return true; |
| 157 } |
| 158 |
| 159 bool NtlmBufferWriter::WriteSignature() { |
| 160 return WriteBytes(NtlmMessage::SIGNATURE, NtlmMessage::SIGNATURE_LEN); |
| 161 } |
| 162 |
| 163 bool NtlmBufferWriter::WriteZeros(size_t count) { |
| 164 if (!CanWrite(count)) |
| 165 return false; |
| 166 |
| 167 memset(GetBufferPtr() + cursor_, 0, count); |
| 168 cursor_ += count; |
| 169 return true; |
| 170 } |
| 171 |
| 172 bool NtlmBufferWriter::WriteMessageType(NtlmMessage::MessageType message_type) { |
| 173 return WriteUInt32(message_type); |
| 174 } |
| 175 |
| 176 bool NtlmBufferWriter::WriteMessageHeader( |
| 177 NtlmMessage::MessageType message_type) { |
| 178 if (!CanWrite(NtlmMessage::SIGNATURE_LEN + sizeof(uint32_t))) |
| 179 return false; |
| 180 |
| 181 if (WriteSignature() && WriteMessageType(message_type)) |
| 182 return true; |
| 183 |
| 184 NOTREACHED(); |
| 185 return false; |
| 186 } |
| 187 |
| 188 // static |
| 189 size_t NtlmBufferWriter::GetStringPayloadLength(const base::string16& str, |
| 190 bool is_unicode) { |
| 191 if (is_unicode) |
| 192 return str.length() * 2; |
| 193 |
| 194 // When |WriteString16AsUTF8| is called with |
| 195 // a |base::string16| the string is effectively converted to |
| 196 // UTF8 by |base::SysWideToNativeMB|. Do the conversion |
| 197 // to ensure that the character count is correct. |
| 198 return base::SysWideToNativeMB(base::UTF16ToWide(str)).length(); |
| 199 } |
| 200 |
| 201 // static |
| 202 size_t NtlmBufferWriter::GetStringPayloadLength(const std::string& str, |
| 203 bool is_unicode) { |
| 204 // When |WriteUnicodePayload| is called with a |std::string| |
| 205 // the string is assumed ASCII and the characters are zero-padded. |
| 206 return is_unicode ? str.length() * 2 : str.length(); |
| 207 } |
| 208 |
| 209 } // namespace net |
OLD | NEW |