1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/ntlm/ntlm_buffer_writer.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <string.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <limits>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
13*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker namespace net::ntlm {
16*6777b538SAndroid Build Coastguard Worker
NtlmBufferWriter(size_t buffer_len)17*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter::NtlmBufferWriter(size_t buffer_len)
18*6777b538SAndroid Build Coastguard Worker : buffer_(buffer_len, 0) {}
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker NtlmBufferWriter::~NtlmBufferWriter() = default;
21*6777b538SAndroid Build Coastguard Worker
CanWrite(size_t len) const22*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::CanWrite(size_t len) const {
23*6777b538SAndroid Build Coastguard Worker if (len == 0)
24*6777b538SAndroid Build Coastguard Worker return true;
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker if (!GetBufferPtr())
27*6777b538SAndroid Build Coastguard Worker return false;
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker DCHECK_LE(GetCursor(), GetLength());
30*6777b538SAndroid Build Coastguard Worker
31*6777b538SAndroid Build Coastguard Worker return (len <= GetLength()) && (GetCursor() <= GetLength() - len);
32*6777b538SAndroid Build Coastguard Worker }
33*6777b538SAndroid Build Coastguard Worker
WriteUInt16(uint16_t value)34*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteUInt16(uint16_t value) {
35*6777b538SAndroid Build Coastguard Worker return WriteUInt<uint16_t>(value);
36*6777b538SAndroid Build Coastguard Worker }
37*6777b538SAndroid Build Coastguard Worker
WriteUInt32(uint32_t value)38*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteUInt32(uint32_t value) {
39*6777b538SAndroid Build Coastguard Worker return WriteUInt<uint32_t>(value);
40*6777b538SAndroid Build Coastguard Worker }
41*6777b538SAndroid Build Coastguard Worker
WriteUInt64(uint64_t value)42*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteUInt64(uint64_t value) {
43*6777b538SAndroid Build Coastguard Worker return WriteUInt<uint64_t>(value);
44*6777b538SAndroid Build Coastguard Worker }
45*6777b538SAndroid Build Coastguard Worker
WriteFlags(NegotiateFlags flags)46*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteFlags(NegotiateFlags flags) {
47*6777b538SAndroid Build Coastguard Worker return WriteUInt32(static_cast<uint32_t>(flags));
48*6777b538SAndroid Build Coastguard Worker }
49*6777b538SAndroid Build Coastguard Worker
WriteBytes(base::span<const uint8_t> bytes)50*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteBytes(base::span<const uint8_t> bytes) {
51*6777b538SAndroid Build Coastguard Worker if (bytes.size() == 0)
52*6777b538SAndroid Build Coastguard Worker return true;
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker if (!CanWrite(bytes.size()))
55*6777b538SAndroid Build Coastguard Worker return false;
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker memcpy(GetBufferPtrAtCursor(), bytes.data(), bytes.size());
58*6777b538SAndroid Build Coastguard Worker AdvanceCursor(bytes.size());
59*6777b538SAndroid Build Coastguard Worker return true;
60*6777b538SAndroid Build Coastguard Worker }
61*6777b538SAndroid Build Coastguard Worker
WriteZeros(size_t count)62*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteZeros(size_t count) {
63*6777b538SAndroid Build Coastguard Worker if (count == 0)
64*6777b538SAndroid Build Coastguard Worker return true;
65*6777b538SAndroid Build Coastguard Worker
66*6777b538SAndroid Build Coastguard Worker if (!CanWrite(count))
67*6777b538SAndroid Build Coastguard Worker return false;
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker memset(GetBufferPtrAtCursor(), 0, count);
70*6777b538SAndroid Build Coastguard Worker AdvanceCursor(count);
71*6777b538SAndroid Build Coastguard Worker return true;
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker
WriteSecurityBuffer(SecurityBuffer sec_buf)74*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteSecurityBuffer(SecurityBuffer sec_buf) {
75*6777b538SAndroid Build Coastguard Worker return WriteUInt16(sec_buf.length) && WriteUInt16(sec_buf.length) &&
76*6777b538SAndroid Build Coastguard Worker WriteUInt32(sec_buf.offset);
77*6777b538SAndroid Build Coastguard Worker }
78*6777b538SAndroid Build Coastguard Worker
WriteAvPairHeader(TargetInfoAvId avid,uint16_t avlen)79*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteAvPairHeader(TargetInfoAvId avid, uint16_t avlen) {
80*6777b538SAndroid Build Coastguard Worker if (!CanWrite(kAvPairHeaderLen))
81*6777b538SAndroid Build Coastguard Worker return false;
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker bool result = WriteUInt16(static_cast<uint16_t>(avid)) && WriteUInt16(avlen);
84*6777b538SAndroid Build Coastguard Worker
85*6777b538SAndroid Build Coastguard Worker DCHECK(result);
86*6777b538SAndroid Build Coastguard Worker return result;
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker
WriteAvPairTerminator()89*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteAvPairTerminator() {
90*6777b538SAndroid Build Coastguard Worker return WriteAvPairHeader(TargetInfoAvId::kEol, 0);
91*6777b538SAndroid Build Coastguard Worker }
92*6777b538SAndroid Build Coastguard Worker
WriteAvPair(const AvPair & pair)93*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteAvPair(const AvPair& pair) {
94*6777b538SAndroid Build Coastguard Worker if (!WriteAvPairHeader(pair))
95*6777b538SAndroid Build Coastguard Worker return false;
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker if (pair.avid == TargetInfoAvId::kFlags) {
98*6777b538SAndroid Build Coastguard Worker if (pair.avlen != sizeof(uint32_t))
99*6777b538SAndroid Build Coastguard Worker return false;
100*6777b538SAndroid Build Coastguard Worker return WriteUInt32(static_cast<uint32_t>(pair.flags));
101*6777b538SAndroid Build Coastguard Worker } else {
102*6777b538SAndroid Build Coastguard Worker return WriteBytes(pair.buffer);
103*6777b538SAndroid Build Coastguard Worker }
104*6777b538SAndroid Build Coastguard Worker }
105*6777b538SAndroid Build Coastguard Worker
WriteUtf8String(const std::string & str)106*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteUtf8String(const std::string& str) {
107*6777b538SAndroid Build Coastguard Worker return WriteBytes(base::as_byte_span(str));
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker
WriteUtf16AsUtf8String(const std::u16string & str)110*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteUtf16AsUtf8String(const std::u16string& str) {
111*6777b538SAndroid Build Coastguard Worker std::string utf8 = base::UTF16ToUTF8(str);
112*6777b538SAndroid Build Coastguard Worker return WriteUtf8String(utf8);
113*6777b538SAndroid Build Coastguard Worker }
114*6777b538SAndroid Build Coastguard Worker
WriteUtf8AsUtf16String(const std::string & str)115*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteUtf8AsUtf16String(const std::string& str) {
116*6777b538SAndroid Build Coastguard Worker std::u16string unicode = base::UTF8ToUTF16(str);
117*6777b538SAndroid Build Coastguard Worker return WriteUtf16String(unicode);
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker
WriteUtf16String(const std::u16string & str)120*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteUtf16String(const std::u16string& str) {
121*6777b538SAndroid Build Coastguard Worker if (str.size() > std::numeric_limits<size_t>::max() / 2)
122*6777b538SAndroid Build Coastguard Worker return false;
123*6777b538SAndroid Build Coastguard Worker
124*6777b538SAndroid Build Coastguard Worker size_t num_bytes = str.size() * 2;
125*6777b538SAndroid Build Coastguard Worker if (num_bytes == 0)
126*6777b538SAndroid Build Coastguard Worker return true;
127*6777b538SAndroid Build Coastguard Worker
128*6777b538SAndroid Build Coastguard Worker if (!CanWrite(num_bytes))
129*6777b538SAndroid Build Coastguard Worker return false;
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker #if defined(ARCH_CPU_BIG_ENDIAN)
132*6777b538SAndroid Build Coastguard Worker uint8_t* ptr = reinterpret_cast<uint8_t*>(GetBufferPtrAtCursor());
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker for (int i = 0; i < num_bytes; i += 2) {
135*6777b538SAndroid Build Coastguard Worker ptr[i] = str[i / 2] & 0xff;
136*6777b538SAndroid Build Coastguard Worker ptr[i + 1] = str[i / 2] >> 8;
137*6777b538SAndroid Build Coastguard Worker }
138*6777b538SAndroid Build Coastguard Worker #else
139*6777b538SAndroid Build Coastguard Worker memcpy(reinterpret_cast<void*>(GetBufferPtrAtCursor()), str.c_str(),
140*6777b538SAndroid Build Coastguard Worker num_bytes);
141*6777b538SAndroid Build Coastguard Worker
142*6777b538SAndroid Build Coastguard Worker #endif
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker AdvanceCursor(num_bytes);
145*6777b538SAndroid Build Coastguard Worker return true;
146*6777b538SAndroid Build Coastguard Worker }
147*6777b538SAndroid Build Coastguard Worker
WriteSignature()148*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteSignature() {
149*6777b538SAndroid Build Coastguard Worker return WriteBytes(kSignature);
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker
WriteMessageType(MessageType message_type)152*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteMessageType(MessageType message_type) {
153*6777b538SAndroid Build Coastguard Worker return WriteUInt32(static_cast<uint32_t>(message_type));
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker
WriteMessageHeader(MessageType message_type)156*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteMessageHeader(MessageType message_type) {
157*6777b538SAndroid Build Coastguard Worker return WriteSignature() && WriteMessageType(message_type);
158*6777b538SAndroid Build Coastguard Worker }
159*6777b538SAndroid Build Coastguard Worker
160*6777b538SAndroid Build Coastguard Worker template <typename T>
WriteUInt(T value)161*6777b538SAndroid Build Coastguard Worker bool NtlmBufferWriter::WriteUInt(T value) {
162*6777b538SAndroid Build Coastguard Worker size_t int_size = sizeof(T);
163*6777b538SAndroid Build Coastguard Worker if (!CanWrite(int_size))
164*6777b538SAndroid Build Coastguard Worker return false;
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < int_size; i++) {
167*6777b538SAndroid Build Coastguard Worker GetBufferPtrAtCursor()[i] = static_cast<uint8_t>(value & 0xff);
168*6777b538SAndroid Build Coastguard Worker value >>= 8;
169*6777b538SAndroid Build Coastguard Worker }
170*6777b538SAndroid Build Coastguard Worker
171*6777b538SAndroid Build Coastguard Worker AdvanceCursor(int_size);
172*6777b538SAndroid Build Coastguard Worker return true;
173*6777b538SAndroid Build Coastguard Worker }
174*6777b538SAndroid Build Coastguard Worker
SetCursor(size_t cursor)175*6777b538SAndroid Build Coastguard Worker void NtlmBufferWriter::SetCursor(size_t cursor) {
176*6777b538SAndroid Build Coastguard Worker DCHECK(GetBufferPtr() && cursor <= GetLength());
177*6777b538SAndroid Build Coastguard Worker
178*6777b538SAndroid Build Coastguard Worker cursor_ = cursor;
179*6777b538SAndroid Build Coastguard Worker }
180*6777b538SAndroid Build Coastguard Worker
181*6777b538SAndroid Build Coastguard Worker } // namespace net::ntlm
182