Skip to content

Commit

Permalink
Add base::HostToNetXX() & NetToHostXX(), and use them to replace hton…
Browse files Browse the repository at this point in the history
…X() & ntohX() in Chrome.

This primarily addresses issues with code using the OS-provided htonX() & ntohX() functions from within the Chrome sandbox.  Under Windows these functions are provided by ws2_32.dll, which is no longer available within Chrome's sandbox.

The new base::HostToNetXX() and NetToHostXX() functions are safe for use by sandboxed code on Windows, and provide a single place where future fixes for other platforms can be made.

BUG=117252

Review URL: http://codereview.chromium.org/9716020

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@129476 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
wez@chromium.org committed Mar 28, 2012
1 parent 97f37d5 commit 9eb7b11
Show file tree
Hide file tree
Showing 31 changed files with 175 additions and 122 deletions.
56 changes: 53 additions & 3 deletions base/sys_byteorder.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.

Expand Down Expand Up @@ -37,6 +37,28 @@
namespace base {

// Returns a value with all bytes in |x| swapped, i.e. reverses the endianness.
inline uint16 ByteSwap(uint16 x) {
#if defined(COMPILER_MSVC)
return _byteswap_ushort(x);
#elif defined(OS_MACOSX)
return OSSwapInt16(x);
#elif defined(OS_OPENBSD)
return swap16(x);
#else
return bswap_16(x);
#endif
}
inline uint32 ByteSwap(uint32 x) {
#if defined(COMPILER_MSVC)
return _byteswap_ulong(x);
#elif defined(OS_MACOSX)
return OSSwapInt32(x);
#elif defined(OS_OPENBSD)
return swap32(x);
#else
return bswap_32(x);
#endif
}
inline uint64 ByteSwap(uint64 x) {
#if defined(COMPILER_MSVC)
return _byteswap_uint64(x);
Expand All @@ -51,7 +73,21 @@ inline uint64 ByteSwap(uint64 x) {

// Converts the bytes in |x| from network to host order (endianness), and
// returns the result.
inline uint64 ntohll(uint64 x) {
inline uint16 NetToHost16(uint16 x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
inline uint32 NetToHost32(uint32 x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
inline uint64 NetToHost64(uint64 x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
Expand All @@ -61,7 +97,21 @@ inline uint64 ntohll(uint64 x) {

// Converts the bytes in |x| from host to network order (endianness), and
// returns the result.
inline uint64 htonll(uint64 x) {
inline uint16 HostToNet16(uint16 x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
inline uint32 HostToNet32(uint32 x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
return x;
#endif
}
inline uint64 HostToNet64(uint64 x) {
#if defined(ARCH_CPU_LITTLE_ENDIAN)
return ByteSwap(x);
#else
Expand Down
19 changes: 10 additions & 9 deletions chrome/browser/chromeos/web_socket_proxy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -841,8 +841,9 @@ void Serv::Run() {
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(0); // let OS allocatate ephemeral port number.
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
// Let the OS allocate a port number.
addr.sin_port = base::HostToNet16(0);
addr.sin_addr.s_addr = base::HostToNet32(INADDR_LOOPBACK);
if (bind(listening_sock_,
reinterpret_cast<struct sockaddr*>(&addr),
sizeof(addr))) {
Expand Down Expand Up @@ -883,8 +884,8 @@ void Serv::Run() {
const int kPort = 10101;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(kPort);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr.sin_port = base::HostToNet16(kPort);
addr.sin_addr.s_addr = base::HostToNet32(INADDR_LOOPBACK);
if (bind(extra_listening_sock_,
reinterpret_cast<struct sockaddr*>(&addr),
sizeof(addr))) {
Expand Down Expand Up @@ -934,7 +935,7 @@ void Serv::Run() {
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&SendNotification, ntohs(addr.sin_port)));
base::Bind(&SendNotification, base::NetToHost16(addr.sin_port)));

LOG(INFO) << "WebSocketProxy: Starting event dispatch loop.";
event_base_dispatch(evbase_);
Expand Down Expand Up @@ -1574,7 +1575,7 @@ void Conn::OnPrimchanRead(struct bufferevent* bev, EventKey evkey) {
{
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_port = htons(cs->destport_);
sa.sin_port = base::HostToNet16(cs->destport_);
if (inet_pton(sa.sin_family = AF_INET,
cs->destaddr_.c_str(),
&sa.sin_addr) == 1) {
Expand All @@ -1595,7 +1596,7 @@ void Conn::OnPrimchanRead(struct bufferevent* bev, EventKey evkey) {
}
struct sockaddr_in6 sa;
memset(&sa, 0, sizeof(sa));
sa.sin6_port = htons(cs->destport_);
sa.sin6_port = base::HostToNet16(cs->destport_);
if (inet_pton(sa.sin6_family = AF_INET6,
cs->destaddr_.c_str(),
&sa.sin6_addr) == 1) {
Expand Down Expand Up @@ -1754,7 +1755,7 @@ void Conn::OnDestResolutionIPv4(int result, char type,
struct sockaddr_in sa;
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(cs->destport_);
sa.sin_port = base::HostToNet16(cs->destport_);
DCHECK(sizeof(sa.sin_addr) == sizeof(struct in_addr));
memcpy(&sa.sin_addr,
static_cast<struct in_addr*>(addr_list) + i,
Expand Down Expand Up @@ -1785,7 +1786,7 @@ void Conn::OnDestResolutionIPv6(int result, char type,
struct sockaddr_in6 sa;
memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET6;
sa.sin6_port = htons(cs->destport_);
sa.sin6_port = base::HostToNet16(cs->destport_);
DCHECK(sizeof(sa.sin6_addr) == sizeof(struct in6_addr));
memcpy(&sa.sin6_addr,
static_cast<struct in6_addr*>(addr_list) + i,
Expand Down
2 changes: 1 addition & 1 deletion chrome/browser/safe_browsing/protocol_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ bool SafeBrowsingProtocolParser::ReadChunkId(
memcpy(chunk_id, *data, sizeof(*chunk_id));
*data += sizeof(*chunk_id);
*remaining -= sizeof(*chunk_id);
*chunk_id = htonl(*chunk_id);
*chunk_id = base::HostToNet32(*chunk_id);
DCHECK_GE(*remaining, 0);
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion chrome/common/metrics/metrics_log_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ inline uint64 HashToUInt64(const std::string& hash) {
uint64 value;
DCHECK_GE(hash.size(), sizeof(value));
memcpy(&value, hash.data(), sizeof(value));
return base::htonll(value);
return base::HostToNet64(value);
}

// Creates an MD5 hash of the given value, and returns hash as a byte buffer
Expand Down
8 changes: 4 additions & 4 deletions content/browser/renderer_host/p2p/socket_host.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.

Expand Down Expand Up @@ -34,15 +34,15 @@ bool P2PSocketHost::GetStunPacketType(
if (data_size < kStunHeaderSize)
return false;

uint32 cookie = ntohl(*reinterpret_cast<const uint32*>(data + 4));
uint32 cookie = base::NetToHost32(*reinterpret_cast<const uint32*>(data + 4));
if (cookie != kStunMagicCookie)
return false;

uint16 length = ntohs(*reinterpret_cast<const uint16*>(data + 2));
uint16 length = base::NetToHost16(*reinterpret_cast<const uint16*>(data + 2));
if (length != data_size - kStunHeaderSize)
return false;

int message_type = ntohs(*reinterpret_cast<const uint16*>(data));
int message_type = base::NetToHost16(*reinterpret_cast<const uint16*>(data));

// Verify that the type is known:
switch (message_type) {
Expand Down
7 changes: 4 additions & 3 deletions content/browser/renderer_host/p2p/socket_host_tcp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,8 @@ void P2PSocketHostTcp::DidCompleteRead(int result) {

read_buffer_->set_offset(read_buffer_->offset() + result);
if (read_buffer_->offset() > kPacketHeaderSize) {
int packet_size =
ntohs(*reinterpret_cast<uint16*>(read_buffer_->StartOfBuffer()));
int packet_size = base::NetToHost16(
*reinterpret_cast<uint16*>(read_buffer_->StartOfBuffer()));
if (packet_size + kPacketHeaderSize <= read_buffer_->offset()) {
// We've got a full packet!
char* start = read_buffer_->StartOfBuffer() + kPacketHeaderSize;
Expand Down Expand Up @@ -221,7 +221,8 @@ void P2PSocketHostTcp::Send(const net::IPEndPoint& to,

int size = kPacketHeaderSize + data.size();
write_buffer_ = new net::DrainableIOBuffer(new net::IOBuffer(size), size);
*reinterpret_cast<uint16*>(write_buffer_->data()) = htons(data.size());
*reinterpret_cast<uint16*>(write_buffer_->data()) =
base::HostToNet16(data.size());
memcpy(write_buffer_->data() + kPacketHeaderSize, &data[0], data.size());

DoWrite();
Expand Down
4 changes: 2 additions & 2 deletions content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.

Expand Down Expand Up @@ -42,7 +42,7 @@ class P2PSocketHostTcpTest : public testing::Test {

std::string IntToSize(int size) {
std::string result;
uint16 size16 = htons(size);
uint16 size16 = base::HostToNet16(size);
result.resize(sizeof(size16));
memcpy(&result[0], &size16, sizeof(size16));
return result;
Expand Down
9 changes: 5 additions & 4 deletions content/browser/renderer_host/p2p/socket_host_test_utils.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.

Expand Down Expand Up @@ -232,10 +232,11 @@ void CreateRandomPacket(std::vector<char>* packet) {

void CreateStunPacket(std::vector<char>* packet, uint16 type) {
CreateRandomPacket(packet);
*reinterpret_cast<uint16*>(&*packet->begin()) = htons(type);
*reinterpret_cast<uint16*>(&*packet->begin()) = base::HostToNet16(type);
*reinterpret_cast<uint16*>(&*packet->begin() + 2) =
htons(packet->size() - kStunHeaderSize);
*reinterpret_cast<uint32*>(&*packet->begin() + 4) = htonl(kStunMagicCookie);
base::HostToNet16(packet->size() - kStunHeaderSize);
*reinterpret_cast<uint32*>(&*packet->begin() + 4) =
base::HostToNet32(kStunMagicCookie);
}

void CreateStunRequest(std::vector<char>* packet) {
Expand Down
8 changes: 4 additions & 4 deletions crypto/encryptor.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2012 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.

Expand All @@ -21,14 +21,14 @@ Encryptor::Counter::~Counter() {
}

bool Encryptor::Counter::Increment() {
uint64 low_num = base::ntohll(counter_.components64[1]);
uint64 low_num = base::NetToHost64(counter_.components64[1]);
uint64 new_low_num = low_num + 1;
counter_.components64[1] = base::htonll(new_low_num);
counter_.components64[1] = base::HostToNet64(new_low_num);

// If overflow occured then increment the most significant component.
if (new_low_num < low_num) {
counter_.components64[0] =
base::htonll(base::ntohll(counter_.components64[0]) + 1);
base::HostToNet64(base::NetToHost64(counter_.components64[0]) + 1);
}

// TODO(hclam): Return false if counter value overflows.
Expand Down
47 changes: 24 additions & 23 deletions crypto/p224.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,11 @@

#include "base/sys_byteorder.h"

#if defined(OS_WIN)
// Allow htonl/ntohl to be called without requiring ws2_32.dll to be loaded,
// which isn't available in Chrome's sandbox. See crbug.com/116591.
// TODO(wez): Replace these calls with base::htonl() etc when available.
#define ntohl(x) _byteswap_ulong(x)
#define htonl(x) _byteswap_ulong(x)
#endif // OS_WIN

namespace {

using base::HostToNet32;
using base::NetToHost32;

// Field element functions.
//
// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1.
Expand Down Expand Up @@ -564,27 +559,33 @@ void ScalarMult(Point* out, const Point& a,
// Get224Bits reads 7 words from in and scatters their contents in
// little-endian form into 8 words at out, 28 bits per output word.
void Get224Bits(uint32* out, const uint32* in) {
out[0] = ntohl(in[6]) & kBottom28Bits;
out[1] = ((ntohl(in[5]) << 4) | (ntohl(in[6]) >> 28)) & kBottom28Bits;
out[2] = ((ntohl(in[4]) << 8) | (ntohl(in[5]) >> 24)) & kBottom28Bits;
out[3] = ((ntohl(in[3]) << 12) | (ntohl(in[4]) >> 20)) & kBottom28Bits;
out[4] = ((ntohl(in[2]) << 16) | (ntohl(in[3]) >> 16)) & kBottom28Bits;
out[5] = ((ntohl(in[1]) << 20) | (ntohl(in[2]) >> 12)) & kBottom28Bits;
out[6] = ((ntohl(in[0]) << 24) | (ntohl(in[1]) >> 8)) & kBottom28Bits;
out[7] = (ntohl(in[0]) >> 4) & kBottom28Bits;
out[0] = NetToHost32(in[6]) & kBottom28Bits;
out[1] = ((NetToHost32(in[5]) << 4) |
(NetToHost32(in[6]) >> 28)) & kBottom28Bits;
out[2] = ((NetToHost32(in[4]) << 8) |
(NetToHost32(in[5]) >> 24)) & kBottom28Bits;
out[3] = ((NetToHost32(in[3]) << 12) |
(NetToHost32(in[4]) >> 20)) & kBottom28Bits;
out[4] = ((NetToHost32(in[2]) << 16) |
(NetToHost32(in[3]) >> 16)) & kBottom28Bits;
out[5] = ((NetToHost32(in[1]) << 20) |
(NetToHost32(in[2]) >> 12)) & kBottom28Bits;
out[6] = ((NetToHost32(in[0]) << 24) |
(NetToHost32(in[1]) >> 8)) & kBottom28Bits;
out[7] = (NetToHost32(in[0]) >> 4) & kBottom28Bits;
}

// Put224Bits performs the inverse operation to Get224Bits: taking 28 bits from
// each of 8 input words and writing them in big-endian order to 7 words at
// out.
void Put224Bits(uint32* out, const uint32* in) {
out[6] = htonl((in[0] >> 0) | (in[1] << 28));
out[5] = htonl((in[1] >> 4) | (in[2] << 24));
out[4] = htonl((in[2] >> 8) | (in[3] << 20));
out[3] = htonl((in[3] >> 12) | (in[4] << 16));
out[2] = htonl((in[4] >> 16) | (in[5] << 12));
out[1] = htonl((in[5] >> 20) | (in[6] << 8));
out[0] = htonl((in[6] >> 24) | (in[7] << 4));
out[6] = HostToNet32((in[0] >> 0) | (in[1] << 28));
out[5] = HostToNet32((in[1] >> 4) | (in[2] << 24));
out[4] = HostToNet32((in[2] >> 8) | (in[3] << 20));
out[3] = HostToNet32((in[3] >> 12) | (in[4] << 16));
out[2] = HostToNet32((in[4] >> 16) | (in[5] << 12));
out[1] = HostToNet32((in[5] >> 20) | (in[6] << 8));
out[0] = HostToNet32((in[6] >> 24) | (in[7] << 4));
}

} // anonymous namespace
Expand Down
5 changes: 2 additions & 3 deletions crypto/symmetric_key_win.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@

#include "crypto/symmetric_key.h"

#include <winsock2.h> // For htonl.

#include <vector>

// TODO(wtc): replace scoped_array by std::vector.
#include "base/memory/scoped_ptr.h"
#include "base/sys_byteorder.h"

namespace crypto {

Expand Down Expand Up @@ -264,7 +263,7 @@ bool ComputePBKDF2Block(HCRYPTHASH hash,
return false;

// Iteration U_1: and append (big-endian) INT (i).
uint32 big_endian_block_index = htonl(block_index);
uint32 big_endian_block_index = base::HostToNet32(block_index);
ok = CryptHashData(safe_hash,
reinterpret_cast<BYTE*>(&big_endian_block_index),
sizeof(big_endian_block_index), 0);
Expand Down
2 changes: 1 addition & 1 deletion jingle/notifier/base/chrome_async_socket_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ class AsyncSocketDataProvider : public net::SocketDataProvider {
// Takes a 32-bit integer in host byte order and converts it to a
// net::IPAddressNumber.
net::IPAddressNumber Uint32ToIPAddressNumber(uint32 ip) {
uint32 ip_nbo = htonl(ip);
uint32 ip_nbo = base::HostToNet32(ip);
const unsigned char* const ip_start =
reinterpret_cast<const unsigned char*>(&ip_nbo);
return net::IPAddressNumber(ip_start, ip_start + (sizeof ip_nbo));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,4 +291,3 @@ void ITransport::Free(ITransport* itrans) {
}

} // namespace port

Loading

0 comments on commit 9eb7b11

Please sign in to comment.