mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-19 19:52:15 +02:00
Eliminate some conversion warnings
- [ipv4.hpp, ipv6.hpp] In both v4 and v6 headers it is safe to cast the hex so as to eliminate the spurious warnings. - [lz4.hpp] Apply value clamp to the hint that is sent to the compressor to prevent a potential conversion overflow. - [zlib.hpp] In compress_gzip, zs.s.avail_in and zs.s.avail_out are theoretically susceptable to overflow. To prevent this we use numeric_cast. In decompress_gzip we do a similar thing for zs.s.avail_in but only value clamp avail_out, since the read loop looks like it will compensate - [buffmt.hpp] It's safe to cast the result of the arithmentically caused promotion back down to char. - [base64.hpp] In Base64 CTOR, changed type of a couple variables to match the type of the table they generate. In decode, perform a static cast to the type of the template elements the function is instantiated for. - [core.hpp] Perform static cast long --> int on value representing number of cores. If we run on systems where there are more cores than int can represent this will behave oddly, but this circumstance seems unlikely at the present time. - [environ.hpp] The casts seem to be safe but I have added a todo ticket to evaluate this change further. - [hexstr.hpp] In render_hex_char there were two conversion warnings and a bug involving out of range input. Those are addressed. In dump_hex the result of some math and logic is now clamped to the range of acceptable input values for string::spaces In parse_hex the result of converting from a hex string to an integral value is cast to the template value_type - [hostport.hpp] The static_cast should be safe because the value produced by validate_port is range checked. - [split.hpp] Applied numeric cast to ensure output of lex.get stays within acceptable type limit. - [stop.hpp] In Stop::Scope It's extremely unlikely but was possible for the vector size to exceed the limit of int. The size now has a much lower limit applied and will throw if it is exceeded. - [string.hpp] Changed the call to toupper/tolower so they call the locale function template instead of the cctype C function. This eliminates the warning and the need for the cast. - [cliproto.hpp] The computation of mss_fix is stored in a size_t and then assigned to an unsigned short. We clamp this assignment to the range of unsigned short. - [tempfile.hpp] In TempFile CTOR suffixLen is computed as one type and consumed as another. Since the CTOR is already throwing for a couple other error conditions, I have added a numeric_cast to the conversion that also throws in case of a value overflow. - [unicode.hpp] In an 8 --> 16 bit string conversion we mask and assign in a way the compiler can't be certain is safe even though it is safe. Added static cast to let the compiler know it's safe. In the second case the class uses unsigned int to store a size, and then uses it in with size_t which generates conversion warnings. I have changed the type of size to size_t - [logperiod.hpp] in log_period changed return type specification to match the actual return type. - [usergroup_retain_cap.hpp] In the unlikely event the caps size (size_t) exceeds the range cap_set_flag can accept, an exception will be thrown. - [crypto_aead.hpp] StaticKey::size provides a size_t where unsigned int is required. We use numeric_cast to check the size() value in the extremely unlikely event it is manipulated to exceed the allowed value. - [packet_id.hpp] Code packs a time_t into a uint32_t for replay packet ID protection purposes. The warning is supressed by a mask and cast since the 32 bit limit is baked into the protocol and the overflow itself does not cause a severe breakage. - [headredact.hpp] Altered code such that the type that stores the find result is compatible with the result from find. Additionally used the npos constant instead of -1. There is a commented out code block that claims to be dropped due to requiring C++ '14 - consider just using that. - [csum.hpp] in csum fold and cfold one has a mask and cast, the second is just a cast to undo a promotion. Both appear safe. - [ipv4.hpp] Values are masked and shifted so the cast should be safe. Added cast. - [ping4.hpp] ICMP ID and sequence number function arguments are changed to the same type as needed by the structure. For IPv4 header version_len 2nd arg is int but sizeof is not, so we cast it. IPv4 tot_len is a uint16_t so we clamp to that value range and compute it once. - [ping6.hpp] Enforces a value constraint on the len argument to csum_icmp, then checks the result of some math to ensure the result will fit in the type it has to fit. In generate_echo_request the ICMP ID and sequence args are changed to match the type they are assigned to in the struct, and added numeric_cast to range check payload_len. - [remotelist.hpp] In get_endpoint, endpoint.port is called with an unsigned int where the function is expecting an unsigned short int. Since parse_number_throw is a function template, we just ask it to return the correct type now. - [compress.hpp] In v2_push we accept an int value that is assigned to an unsigned char we push to the buffer. I changed the function to accept an unsigned char directly. Added unit tests - thanks Mark Deric. Signed-off-by: Charlie Vigue <charlie.vigue@openvpn.net>
This commit is contained in:
parent
1f5aa58223
commit
f38e97e1c3
@ -274,7 +274,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial
|
||||
const int bl = parse_hex_char(s[idx + 1]);
|
||||
if (bh == -1 || bl == -1)
|
||||
throw ipv4_exception("parse hex error");
|
||||
ret.u.bytes[Endian::e4(di--)] = (bh << 4) + bl;
|
||||
ret.u.bytes[Endian::e4(di--)] = static_cast<unsigned char>((bh << 4) + bl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -289,7 +289,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial
|
||||
const unsigned char b = u.bytes[Endian::e4rev(i)];
|
||||
if (b || firstnonzero || i == 3)
|
||||
{
|
||||
const char bh = b >> 4;
|
||||
const char bh = static_cast<decltype(bh)>(b >> 4);
|
||||
if (bh || firstnonzero)
|
||||
ret += render_hex_char(bh);
|
||||
ret += render_hex_char(b & 0x0F);
|
||||
|
@ -176,7 +176,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial
|
||||
const int bl = parse_hex_char(s[idx + 1]);
|
||||
if (bh == -1 || bl == -1)
|
||||
throw ipv6_exception("parse hex error");
|
||||
ret.u.bytes[Endian::e16(di--)] = (bh << 4) + bl;
|
||||
ret.u.bytes[Endian::e16(di--)] = static_cast<unsigned char>((bh << 4) + bl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -191,7 +191,7 @@ class Addr // NOTE: must be union-legal, so default constructor does not initial
|
||||
const unsigned char b = u.bytes[Endian::e16rev(i)];
|
||||
if (b || firstnonzero || i == 15)
|
||||
{
|
||||
const char bh = b >> 4;
|
||||
const char bh = static_cast<decltype(bh)>(b >> 4);
|
||||
if (bh || firstnonzero)
|
||||
ret += render_hex_char(bh);
|
||||
ret += render_hex_char(b & 0x0F);
|
||||
|
@ -68,7 +68,7 @@ class UnsignedDecimal
|
||||
T d = value_ / T(10);
|
||||
T r = value_ % T(10);
|
||||
value_ = d;
|
||||
return '0' + r;
|
||||
return static_cast<char>('0' + r);
|
||||
}
|
||||
|
||||
bool is_zero() const
|
||||
|
@ -25,12 +25,15 @@
|
||||
|
||||
#include <lz4.h>
|
||||
|
||||
#include <openvpn/common/clamp_typerange.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/socktypes.hpp> // for ntohl/htonl
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace LZ4 {
|
||||
using openvpn::numeric_util::clamp_to_typerange;
|
||||
|
||||
namespace openvpn::LZ4 {
|
||||
|
||||
OPENVPN_EXCEPTION(lz4_error);
|
||||
|
||||
inline BufferPtr compress(const ConstBuffer &src,
|
||||
@ -47,7 +50,7 @@ inline BufferPtr compress(const ConstBuffer &src,
|
||||
|
||||
// as a hint to receiver, write the decompressed size
|
||||
{
|
||||
const std::uint32_t size = htonl(src.size());
|
||||
const std::uint32_t size = htonl(clamp_to_typerange<uint32_t>(src.size()));
|
||||
dest->write(&size, sizeof(size));
|
||||
}
|
||||
|
||||
@ -96,5 +99,4 @@ inline BufferPtr decompress(const ConstBuffer &source,
|
||||
return dest;
|
||||
}
|
||||
|
||||
} // namespace LZ4
|
||||
} // namespace openvpn
|
||||
} // namespace openvpn::LZ4
|
||||
|
@ -28,11 +28,17 @@
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <openvpn/common/clamp_typerange.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/numeric_cast.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/buffer/buflist.hpp>
|
||||
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
using namespace numeric_util;
|
||||
|
||||
namespace ZLib {
|
||||
OPENVPN_EXCEPTION(zlib_error);
|
||||
|
||||
@ -74,7 +80,7 @@ inline BufferPtr compress_gzip(BufferPtr src,
|
||||
int status;
|
||||
ZStream zs;
|
||||
zs.s.next_in = src->data();
|
||||
zs.s.avail_in = src->size();
|
||||
zs.s.avail_in = numeric_cast<decltype(zs.s.avail_in)>(src->size());
|
||||
status = ::deflateInit2(&zs.s,
|
||||
level,
|
||||
Z_DEFLATED,
|
||||
@ -87,7 +93,7 @@ inline BufferPtr compress_gzip(BufferPtr src,
|
||||
BufferPtr b = new BufferAllocated(outcap + headroom + tailroom, 0);
|
||||
b->init_headroom(headroom);
|
||||
zs.s.next_out = b->data();
|
||||
zs.s.avail_out = outcap;
|
||||
zs.s.avail_out = numeric_cast<decltype(zs.s.avail_out)>(outcap);
|
||||
status = ::deflate(&zs.s, Z_FINISH);
|
||||
if (status != Z_STREAM_END)
|
||||
OPENVPN_THROW(zlib_error, "zlib deflate failed, error=" << status);
|
||||
@ -120,7 +126,7 @@ inline BufferPtr decompress_gzip(BufferPtr src,
|
||||
int status;
|
||||
ZStream zs;
|
||||
zs.s.next_in = src->data();
|
||||
zs.s.avail_in = src->size();
|
||||
zs.s.avail_in = numeric_cast<decltype(zs.s.avail_in)>(src->size());
|
||||
status = ::inflateInit2(&zs.s, GZIP_ENCODING + window_bits);
|
||||
if (status != Z_OK)
|
||||
OPENVPN_THROW(zlib_error, "zlib inflateinit2 failed, error=" << status);
|
||||
@ -136,7 +142,7 @@ inline BufferPtr decompress_gzip(BufferPtr src,
|
||||
b->init_headroom(hr);
|
||||
const size_t avail = b->remaining(tr);
|
||||
zs.s.next_out = b->data();
|
||||
zs.s.avail_out = avail;
|
||||
zs.s.avail_out = clamp_to_typerange<decltype(zs.s.avail_out)>(avail);
|
||||
status = ::inflate(&zs.s, Z_SYNC_FLUSH);
|
||||
if (status != Z_OK && status != Z_STREAM_END)
|
||||
OPENVPN_THROW(zlib_error, "zlib inflate failed, error=" << status);
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include <openvpn/common/count.hpp>
|
||||
#include <openvpn/common/string.hpp>
|
||||
#include <openvpn/common/base64.hpp>
|
||||
#include <openvpn/common/clamp_typerange.hpp>
|
||||
#include <openvpn/ip/ptb.hpp>
|
||||
#include <openvpn/tun/client/tunbase.hpp>
|
||||
#include <openvpn/transport/client/transbase.hpp>
|
||||
@ -73,8 +74,9 @@
|
||||
#define OPENVPN_LOG_CLIPROTO(x)
|
||||
#endif
|
||||
|
||||
namespace openvpn {
|
||||
namespace ClientProto {
|
||||
using openvpn::numeric_util::clamp_to_typerange;
|
||||
|
||||
namespace openvpn::ClientProto {
|
||||
|
||||
struct NotifyCallback
|
||||
{
|
||||
@ -416,10 +418,12 @@ class Session : ProtoContext,
|
||||
const ProtoContext::Config &c = Base::conf();
|
||||
// when calculating mss, we take IPv4 and TCP headers into account
|
||||
// here we need to add it back since we check the whole IP packet size, not just TCP payload
|
||||
size_t mss_no_tcp_ip_encap = (size_t)c.mss_fix + (20 + 20);
|
||||
constexpr size_t MinTcpHeader = 20;
|
||||
constexpr size_t MinIpHeader = 20;
|
||||
size_t mss_no_tcp_ip_encap = c.mss_fix + (MinTcpHeader + MinIpHeader);
|
||||
if (c.mss_fix > 0 && buf.size() > mss_no_tcp_ip_encap)
|
||||
{
|
||||
Ptb::generate_icmp_ptb(buf, mss_no_tcp_ip_encap);
|
||||
Ptb::generate_icmp_ptb(buf, clamp_to_typerange<unsigned short>(mss_no_tcp_ip_encap));
|
||||
tun->tun_send(buf);
|
||||
}
|
||||
else
|
||||
@ -852,7 +856,7 @@ class Session : ProtoContext,
|
||||
{
|
||||
try
|
||||
{
|
||||
timeout = std::stoul(timeout_str);
|
||||
timeout = clamp_to_typerange<unsigned int>(std::stoul(timeout_str));
|
||||
// Cap the timeout to end well before renegotiation starts
|
||||
timeout = std::min(timeout, static_cast<decltype(timeout)>(conf().renegotiate.to_seconds() / 2));
|
||||
}
|
||||
@ -1374,7 +1378,6 @@ class Session : ProtoContext,
|
||||
std::ofstream packet_log;
|
||||
#endif
|
||||
};
|
||||
} // namespace ClientProto
|
||||
} // namespace openvpn
|
||||
} // namespace openvpn::ClientProto
|
||||
|
||||
#endif
|
||||
|
@ -194,7 +194,7 @@ class RemoteList : public RC<thread_unsafe_refcount>
|
||||
if (res_addr_list && index < res_addr_list->size())
|
||||
{
|
||||
endpoint.address((*res_addr_list)[index]->addr.to_asio());
|
||||
endpoint.port(parse_number_throw<unsigned int>(server_port, "remote_port"));
|
||||
endpoint.port(parse_number_throw<unsigned short>(server_port, "remote_port"));
|
||||
OPENVPN_LOG_REMOTELIST("*** RemoteList::Item endpoint GET[" << index << "] " << endpoint << ' ' << to_string());
|
||||
return true;
|
||||
}
|
||||
|
@ -41,7 +41,10 @@ class Base64
|
||||
class ConstUCharWrap
|
||||
{
|
||||
public:
|
||||
ConstUCharWrap(const unsigned char *data, size_t size)
|
||||
using value_type = unsigned char;
|
||||
|
||||
public:
|
||||
ConstUCharWrap(const value_type *data, size_t size)
|
||||
: data_(data),
|
||||
size_(size)
|
||||
{
|
||||
@ -51,14 +54,14 @@ class Base64
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
unsigned char operator[](const size_t i) const
|
||||
value_type operator[](const size_t i) const
|
||||
{
|
||||
return data_[i];
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
const unsigned char *data_;
|
||||
const value_type *data_;
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
@ -70,12 +73,15 @@ class Base64
|
||||
class UCharWrap
|
||||
{
|
||||
public:
|
||||
UCharWrap(unsigned char *data, size_t size)
|
||||
using value_type = unsigned char;
|
||||
|
||||
public:
|
||||
UCharWrap(value_type *data, size_t size)
|
||||
: data(data), size(size), index(0)
|
||||
{
|
||||
}
|
||||
|
||||
void push_back(unsigned char c)
|
||||
void push_back(value_type c)
|
||||
{
|
||||
if (index >= size)
|
||||
throw base64_decode_out_of_bound_error();
|
||||
@ -83,7 +89,7 @@ class Base64
|
||||
data[index++] = c;
|
||||
}
|
||||
|
||||
unsigned char *data;
|
||||
value_type *data;
|
||||
size_t size;
|
||||
size_t index;
|
||||
};
|
||||
@ -99,7 +105,7 @@ class Base64
|
||||
// build encoding map
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int j = 65;
|
||||
unsigned char j = 65;
|
||||
for (i = 0; i < 62; ++i)
|
||||
{
|
||||
enc[i] = j++;
|
||||
@ -209,13 +215,14 @@ class Base64
|
||||
const char *endp = str.c_str() + str.length();
|
||||
for (const char *p = str.c_str(); p < endp; p += 4)
|
||||
{
|
||||
using vvalue_t = typename V::value_type;
|
||||
unsigned int marker;
|
||||
const unsigned int val = token_decode(p, std::min(endp - p, ptrdiff_t(4)), marker);
|
||||
dest.push_back((val >> 16) & 0xff);
|
||||
dest.push_back(static_cast<vvalue_t>((val >> 16) & 0xff));
|
||||
if (marker < 2)
|
||||
dest.push_back((val >> 8) & 0xff);
|
||||
dest.push_back(static_cast<vvalue_t>((val >> 8) & 0xff));
|
||||
if (marker < 1)
|
||||
dest.push_back(val & 0xff);
|
||||
dest.push_back(static_cast<vvalue_t>(val & 0xff));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ inline int n_cores()
|
||||
long ret = ::sysconf(_SC_NPROCESSORS_ONLN);
|
||||
if (ret <= 0)
|
||||
ret = 1;
|
||||
return ret;
|
||||
return static_cast<int>(ret);
|
||||
#elif defined(OPENVPN_PLATFORM_WIN)
|
||||
SYSTEM_INFO si;
|
||||
::GetSystemInfo(&si);
|
||||
|
@ -81,12 +81,12 @@ class Environ : public std::vector<std::string>
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
if (name == s.substr(0, pos))
|
||||
return i;
|
||||
return static_cast<int>(i); // TODO: [OVPN3-928] Evaluate the safety of casting this down
|
||||
}
|
||||
else
|
||||
{
|
||||
if (name == s)
|
||||
return i;
|
||||
return static_cast<int>(i); // Same as above
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
@ -27,10 +27,14 @@
|
||||
#include <string>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <openvpn/common/clamp_typerange.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/string.hpp>
|
||||
|
||||
using namespace openvpn::numeric_util;
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
/**
|
||||
@ -47,6 +51,8 @@ namespace openvpn {
|
||||
*/
|
||||
inline char render_hex_char(const int c, const bool caps = false)
|
||||
{
|
||||
if (c < 0)
|
||||
return '?';
|
||||
if (c < 10)
|
||||
return '0' + c;
|
||||
else if (c < 16)
|
||||
@ -55,7 +61,6 @@ inline char render_hex_char(const int c, const bool caps = false)
|
||||
return '?';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parses a character in the range {0..9,A-F,a-f} to an
|
||||
* integer value. Used to convert hexadecimal character to integer.
|
||||
@ -284,7 +289,7 @@ inline std::string dump_hex(const unsigned char *data, size_t size)
|
||||
chars += '.';
|
||||
}
|
||||
if (i)
|
||||
os << string::spaces(2 + (((i - 1) & mask) ^ mask) * 3) << chars << std::endl;
|
||||
os << string::spaces(clamp_to_typerange<int>(2 + (((i - 1) & mask) ^ mask) * 3)) << chars << std::endl;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@ -356,6 +361,7 @@ OPENVPN_SIMPLE_EXCEPTION(parse_hex_error);
|
||||
template <typename V>
|
||||
inline void parse_hex(V &dest, const std::string &str)
|
||||
{
|
||||
using vvalue_t = typename V::value_type;
|
||||
const int len = int(str.length());
|
||||
int i;
|
||||
for (i = 0; i <= len - 2; i += 2)
|
||||
@ -364,7 +370,7 @@ inline void parse_hex(V &dest, const std::string &str)
|
||||
const int low = parse_hex_char(str[i + 1]);
|
||||
if (high == -1 || low == -1)
|
||||
throw parse_hex_error();
|
||||
dest.push_back((high << 4) + low);
|
||||
dest.push_back(static_cast<vvalue_t>((high << 4) + low));
|
||||
}
|
||||
if (i != len)
|
||||
throw parse_hex_error(); // straggler char
|
||||
|
@ -59,7 +59,7 @@ inline unsigned short parse_port(const std::string &port, const std::string &tit
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
validate_port(port, title, &ret);
|
||||
return ret;
|
||||
return static_cast<unsigned short>(ret);
|
||||
}
|
||||
|
||||
// An IP address is also considered to be a valid host
|
||||
|
@ -32,9 +32,13 @@
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/lex.hpp>
|
||||
#include <openvpn/common/numeric_cast.hpp>
|
||||
|
||||
|
||||
using namespace openvpn::numeric_util;
|
||||
|
||||
namespace openvpn::Split {
|
||||
|
||||
namespace openvpn {
|
||||
namespace Split {
|
||||
enum
|
||||
{
|
||||
TRIM_LEADING_SPACES = (1 << 0),
|
||||
@ -122,7 +126,7 @@ inline void by_space_void(V &ret, const std::string &input, LIM *lim = nullptr)
|
||||
defined = true;
|
||||
if (lex.available())
|
||||
{
|
||||
const char tc = lex.get();
|
||||
const char tc = numeric_cast<char>(lex.get());
|
||||
if (!SPACE::is_space(tc) || lex.in_quote())
|
||||
{
|
||||
defined = true;
|
||||
@ -154,7 +158,6 @@ inline V by_space(const std::string &input, LIM *lim = nullptr)
|
||||
by_space_void<V, LEX, SPACE, LIM>(ret, input, lim);
|
||||
return ret;
|
||||
}
|
||||
} // namespace Split
|
||||
} // namespace openvpn
|
||||
} // namespace openvpn::Split
|
||||
|
||||
#endif // OPENVPN_COMMON_SPLIT_H
|
||||
|
@ -27,7 +27,12 @@
|
||||
#include <utility>
|
||||
#include <mutex>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
|
||||
OPENVPN_EXCEPTION_INHERIT(std::range_error, openvpn_stop_limit);
|
||||
|
||||
namespace openvpn {
|
||||
|
||||
class Stop
|
||||
{
|
||||
public:
|
||||
@ -41,6 +46,7 @@ class Stop
|
||||
method(std::move(method_arg)),
|
||||
index(-1)
|
||||
{
|
||||
constexpr int stop_index_limit = 1000;
|
||||
if (stop)
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> lock(stop->mutex);
|
||||
@ -51,7 +57,10 @@ class Stop
|
||||
}
|
||||
else
|
||||
{
|
||||
index = stop->scopes.size();
|
||||
if (index > stop_index_limit)
|
||||
throw openvpn_stop_limit("Stop count limit exceeded");
|
||||
|
||||
index = static_cast<decltype(index)>(stop->scopes.size());
|
||||
stop->scopes.push_back(this);
|
||||
}
|
||||
}
|
||||
@ -104,10 +113,10 @@ class Stop
|
||||
return stop && stop->stop_called;
|
||||
}
|
||||
|
||||
private:
|
||||
Stop(const Stop &) = delete;
|
||||
Stop &operator=(const Stop &) = delete;
|
||||
|
||||
private:
|
||||
void prune()
|
||||
{
|
||||
while (scopes.size() && !scopes.back())
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <locale>
|
||||
#include <algorithm>
|
||||
|
||||
#include <openvpn/common/platform.hpp>
|
||||
@ -582,18 +582,20 @@ inline std::string trim_copy(const std::string &str)
|
||||
inline std::string to_upper_copy(const std::string &str)
|
||||
{
|
||||
std::string ret;
|
||||
std::locale loc;
|
||||
ret.reserve(str.length());
|
||||
for (const auto &c : str)
|
||||
ret.push_back(std::toupper(static_cast<unsigned char>(c)));
|
||||
ret.push_back(std::toupper(c, loc));
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline std::string to_lower_copy(const std::string &str)
|
||||
{
|
||||
std::string ret;
|
||||
std::locale loc;
|
||||
ret.reserve(str.length());
|
||||
for (const auto &c : str)
|
||||
ret.push_back(std::tolower(static_cast<unsigned char>(c)));
|
||||
ret.push_back(std::tolower(c, loc));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -38,11 +38,14 @@
|
||||
#include <memory>
|
||||
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/numeric_cast.hpp>
|
||||
#include <openvpn/common/scoped_fd.hpp>
|
||||
#include <openvpn/common/write.hpp>
|
||||
#include <openvpn/common/strerror.hpp>
|
||||
#include <openvpn/buffer/bufread.hpp>
|
||||
|
||||
using openvpn::numeric_util::numeric_cast;
|
||||
|
||||
namespace openvpn {
|
||||
class TempFile
|
||||
{
|
||||
@ -54,13 +57,17 @@ class TempFile
|
||||
: fn(new char[fn_template.length() + 1]),
|
||||
del(fn_delete)
|
||||
{
|
||||
constexpr char pattern[] = "XXXXXX";
|
||||
constexpr size_t patternLen = sizeof(pattern) - 1;
|
||||
std::memcpy(fn.get(), fn_template.c_str(), fn_template.length() + 1);
|
||||
const size_t pos = fn_template.find("XXXXXX");
|
||||
const size_t pos = fn_template.rfind(pattern);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
const int suffixlen = fn_template.length() - pos - 6;
|
||||
if (suffixlen > 0)
|
||||
fd.reset(::mkstemps(fn.get(), suffixlen));
|
||||
if (fn_template.length() > pos + patternLen)
|
||||
{
|
||||
const auto suffixlen = fn_template.length() - pos - patternLen;
|
||||
fd.reset(::mkstemps(fn.get(), numeric_cast<int>(suffixlen)));
|
||||
}
|
||||
else
|
||||
fd.reset(::mkstemp(fn.get()));
|
||||
if (!fd.defined())
|
||||
|
@ -236,8 +236,8 @@ inline BufferPtr string_to_utf16(const STRING &str)
|
||||
UTF8 *d = ret->data();
|
||||
for (const UTF16 *s = utf16_dest.get(); s < dest; ++s)
|
||||
{
|
||||
*d++ = *s & 0xFF;
|
||||
*d++ = (*s >> 8) & 0xFF;
|
||||
*d++ = static_cast<UTF8>(*s & 0xFF);
|
||||
*d++ = static_cast<UTF8>((*s >> 8) & 0xFF);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -298,7 +298,7 @@ class UTF8Iterator
|
||||
|
||||
private:
|
||||
const unsigned char *str;
|
||||
unsigned int size;
|
||||
size_t size;
|
||||
};
|
||||
} // namespace Unicode
|
||||
} // namespace openvpn
|
||||
|
@ -117,7 +117,7 @@ class Compress : public RC<thread_unsafe_refcount>
|
||||
|
||||
// Push a COMPRESS_V2 header byte (value).
|
||||
// Pass value == 0 to omit push.
|
||||
void v2_push(Buffer &buf, int value)
|
||||
void v2_push(Buffer &buf, unsigned char value)
|
||||
{
|
||||
unsigned char uc = buf[0];
|
||||
if (value == 0 && uc != COMPRESS_V2_ESCAPE)
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/exception.hpp>
|
||||
#include <openvpn/common/numeric_cast.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
#include <openvpn/frame/frame.hpp>
|
||||
#include <openvpn/crypto/static_key.hpp>
|
||||
@ -41,8 +42,9 @@
|
||||
// [4-byte
|
||||
// IV head]
|
||||
|
||||
namespace openvpn {
|
||||
namespace AEAD {
|
||||
using openvpn::numeric_util::numeric_cast;
|
||||
|
||||
namespace openvpn::AEAD {
|
||||
|
||||
OPENVPN_EXCEPTION(aead_error);
|
||||
|
||||
@ -252,8 +254,16 @@ class Crypto : public CryptoDCInstance
|
||||
|
||||
void init_cipher(StaticKey &&encrypt_key, StaticKey &&decrypt_key) override
|
||||
{
|
||||
e.impl.init(libctx, cipher, encrypt_key.data(), encrypt_key.size(), CRYPTO_API::CipherContextAEAD::ENCRYPT);
|
||||
d.impl.init(libctx, cipher, decrypt_key.data(), decrypt_key.size(), CRYPTO_API::CipherContextAEAD::DECRYPT);
|
||||
e.impl.init(libctx,
|
||||
cipher,
|
||||
encrypt_key.data(),
|
||||
numeric_cast<unsigned int>(encrypt_key.size()),
|
||||
CRYPTO_API::CipherContextAEAD::ENCRYPT);
|
||||
d.impl.init(libctx,
|
||||
cipher,
|
||||
decrypt_key.data(),
|
||||
numeric_cast<unsigned int>(decrypt_key.size()),
|
||||
CRYPTO_API::CipherContextAEAD::DECRYPT);
|
||||
}
|
||||
|
||||
void init_hmac(StaticKey &&encrypt_key,
|
||||
@ -354,7 +364,6 @@ class CryptoContext : public CryptoDCContext
|
||||
SessionStats::Ptr stats;
|
||||
SSLLib::Ctx libctx;
|
||||
};
|
||||
} // namespace AEAD
|
||||
} // namespace openvpn
|
||||
} // namespace openvpn::AEAD
|
||||
|
||||
#endif
|
||||
|
@ -123,7 +123,9 @@ struct PacketID
|
||||
void write(Buffer &buf, const int form, const bool prepend) const
|
||||
{
|
||||
const id_t net_id = htonl(id);
|
||||
const net_time_t net_time = htonl(time);
|
||||
const net_time_t net_time = htonl(static_cast<uint32_t>(time & 0x00000000FFFFFFFF));
|
||||
// TODO: [OVPN3-931] Make our code handle rollover of this value gracefully as possible
|
||||
// since at the current time this will probably force a reconnect.
|
||||
|
||||
if (prepend)
|
||||
{
|
||||
@ -260,6 +262,7 @@ class PacketIDReceiveType
|
||||
|
||||
OPENVPN_SIMPLE_EXCEPTION(packet_id_not_initialized);
|
||||
|
||||
// TODO: [OVPN3-933] Consider RAII'ifying this code
|
||||
PacketIDReceiveType()
|
||||
: initialized_(false)
|
||||
{
|
||||
@ -350,7 +353,7 @@ class PacketIDReceiveType
|
||||
if (!mod)
|
||||
return Error::SUCCESS;
|
||||
base = REPLAY_INDEX(-1);
|
||||
history[base / 8] |= (1 << (base % 8));
|
||||
history[base / 8] |= static_cast<uint8_t>(1 << (base % 8));
|
||||
if (extent < REPLAY_WINDOW_SIZE)
|
||||
++extent;
|
||||
id_high = pin.id;
|
||||
@ -364,14 +367,14 @@ class PacketIDReceiveType
|
||||
if (delta < REPLAY_WINDOW_SIZE)
|
||||
{
|
||||
base = REPLAY_INDEX(-delta);
|
||||
history[base / 8] |= (1 << (base % 8));
|
||||
history[base / 8] |= static_cast<uint8_t>(1 << (base % 8));
|
||||
extent += delta;
|
||||
if (extent > REPLAY_WINDOW_SIZE)
|
||||
extent = REPLAY_WINDOW_SIZE;
|
||||
for (unsigned i = 1; i < delta; ++i)
|
||||
{
|
||||
const unsigned int newbase = REPLAY_INDEX(i);
|
||||
history[newbase / 8] &= ~(1 << (newbase % 8));
|
||||
history[newbase / 8] &= static_cast<uint8_t>(~(1 << (newbase % 8)));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -395,7 +398,7 @@ class PacketIDReceiveType
|
||||
{
|
||||
const unsigned int ri = REPLAY_INDEX(delta);
|
||||
std::uint8_t *p = &history[ri / 8];
|
||||
const std::uint8_t mask = (1 << (ri % 8));
|
||||
const std::uint8_t mask = static_cast<uint8_t>(1 << (ri % 8));
|
||||
if (*p & mask)
|
||||
return Error::PKTID_REPLAY;
|
||||
if (!mod)
|
||||
|
@ -32,7 +32,7 @@ inline std::string headers_redact(const std::string &headers)
|
||||
#ifdef OPENVPN_HTTP_HEADERS_NO_REDACT
|
||||
return headers;
|
||||
#else
|
||||
// C++14 only solution (not compatible with RHEL7/CentOS7)
|
||||
// Alternative regex implementation:
|
||||
// static const std::regex re(R"((authorization[\s:=]+basic\s+)([^\s]+))", std::regex_constants::ECMAScript | std::regex_constants::icase);
|
||||
// return std::regex_replace(headers, re, "$1[REDACTED]");
|
||||
std::stringstream result;
|
||||
@ -41,20 +41,18 @@ inline std::string headers_redact(const std::string &headers)
|
||||
|
||||
for (std::string line; std::getline(iss, line);)
|
||||
{
|
||||
int authpos;
|
||||
if ((authpos = line.find("Authorization: ")) != -1)
|
||||
if (auto authpos = line.find("Authorization: "); authpos != std::string::npos)
|
||||
{
|
||||
auto auth = line.substr(authpos);
|
||||
auto argument = auth.substr(auth.find(' ') + 1);
|
||||
std::string authtype;
|
||||
int arg1 = -1;
|
||||
if ((arg1 = argument.find(' ')) != -1)
|
||||
if (auto arg1 = argument.find(' '); arg1 != std::string::npos)
|
||||
{
|
||||
authtype = argument.substr(0, arg1);
|
||||
}
|
||||
result << line.substr(0, authpos) << "Authorization: " << authtype << " [REDACTED]\r" << std::endl;
|
||||
}
|
||||
else if ((authpos = line.find("authorization=basic ")) != -1)
|
||||
else if ((authpos = line.find("authorization=basic ")) != std::string::npos)
|
||||
{
|
||||
result << line.substr(0, authpos) << "authorization=basic [REDACTED]\r" << std::endl;
|
||||
}
|
||||
|
@ -36,12 +36,12 @@ inline std::uint16_t fold(std::uint32_t sum)
|
||||
{
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
return sum;
|
||||
return static_cast<uint16_t>(sum & 0x0000FFFF);
|
||||
}
|
||||
|
||||
inline std::uint16_t cfold(const std::uint32_t sum)
|
||||
{
|
||||
return ~fold(sum);
|
||||
return static_cast<uint16_t>(~fold(sum));
|
||||
}
|
||||
|
||||
inline std::uint32_t unfold(const std::uint16_t sum)
|
||||
|
@ -40,7 +40,7 @@ struct IPv4Header
|
||||
static std::uint8_t ver_len(const unsigned int version,
|
||||
const unsigned int len)
|
||||
{
|
||||
return ((len >> 2) & 0x0F) | (version & 0x0F) << 4;
|
||||
return static_cast<uint8_t>(((len >> 2) & 0x0F) | (version & 0x0F) << 4);
|
||||
}
|
||||
|
||||
std::uint8_t version_len;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include <openvpn/common/clamp_typerange.hpp>
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
@ -33,16 +34,17 @@
|
||||
#include <openvpn/ip/icmp4.hpp>
|
||||
#include <openvpn/ip/csum.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace Ping4 {
|
||||
using openvpn::numeric_util::clamp_to_typerange;
|
||||
|
||||
namespace openvpn::Ping4 {
|
||||
|
||||
inline void generate_echo_request(Buffer &buf,
|
||||
const IPv4::Addr &src,
|
||||
const IPv4::Addr &dest,
|
||||
const void *extra_data,
|
||||
const size_t extra_data_size,
|
||||
const unsigned int id,
|
||||
const unsigned int seq_num,
|
||||
const uint16_t id,
|
||||
const uint16_t seq_num,
|
||||
const size_t total_size,
|
||||
std::string *log_info)
|
||||
{
|
||||
@ -51,13 +53,14 @@ inline void generate_echo_request(Buffer &buf,
|
||||
if (log_info)
|
||||
*log_info = "PING4 " + src.to_string() + " -> " + dest.to_string() + " id=" + std::to_string(id) + " seq_num=" + std::to_string(seq_num) + " data_size=" + std::to_string(data_size);
|
||||
|
||||
std::uint8_t *b = buf.write_alloc(sizeof(ICMPv4) + data_size);
|
||||
const auto total_length = clamp_to_typerange<uint16_t>(sizeof(ICMPv4) + data_size);
|
||||
std::uint8_t *b = buf.write_alloc(total_length);
|
||||
ICMPv4 *icmp = (ICMPv4 *)b;
|
||||
|
||||
// IP Header
|
||||
icmp->head.version_len = IPv4Header::ver_len(4, sizeof(IPv4Header));
|
||||
icmp->head.version_len = IPv4Header::ver_len(4, static_cast<int>(sizeof(IPv4Header)));
|
||||
icmp->head.tos = 0;
|
||||
icmp->head.tot_len = htons(sizeof(ICMPv4) + data_size);
|
||||
icmp->head.tot_len = htons(total_length);
|
||||
icmp->head.id = 0;
|
||||
icmp->head.frag_off = 0;
|
||||
icmp->head.ttl = 64;
|
||||
@ -109,5 +112,4 @@ inline void generate_echo_reply(Buffer &buf,
|
||||
if (log_info)
|
||||
*log_info = "ECHO4_REPLY size=" + std::to_string(buf.size()) + ' ' + IPv4::Addr::from_uint32_net(icmp->head.saddr).to_string() + " -> " + IPv4::Addr::from_uint32_net(icmp->head.daddr).to_string();
|
||||
}
|
||||
} // namespace Ping4
|
||||
} // namespace openvpn
|
||||
} // namespace openvpn::Ping4
|
@ -25,6 +25,7 @@
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include <openvpn/common/numeric_cast.hpp>
|
||||
#include <openvpn/common/size.hpp>
|
||||
#include <openvpn/common/socktypes.hpp>
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
@ -33,8 +34,9 @@
|
||||
#include <openvpn/ip/icmp6.hpp>
|
||||
#include <openvpn/ip/csum.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace Ping6 {
|
||||
using namespace openvpn::numeric_util;
|
||||
|
||||
namespace openvpn::Ping6 {
|
||||
|
||||
inline static const std::uint16_t *get_addr16(const struct in6_addr *addr)
|
||||
{
|
||||
@ -90,9 +92,13 @@ inline std::uint16_t csum_ipv6_pseudo(const struct in6_addr *saddr,
|
||||
// len must be >= sizeof(ICMPv6)
|
||||
inline std::uint16_t csum_icmp(const ICMPv6 *icmp, const size_t len)
|
||||
{
|
||||
if (len < sizeof(IPv6Header))
|
||||
throw std::range_error("Argument 'len' too small");
|
||||
|
||||
auto lenArg = numeric_cast<uint32_t>(len - sizeof(IPv6Header));
|
||||
return csum_ipv6_pseudo(&icmp->head.saddr,
|
||||
&icmp->head.daddr,
|
||||
len - sizeof(IPv6Header),
|
||||
lenArg,
|
||||
IPCommon::ICMPv6,
|
||||
IPChecksum::compute((std::uint8_t *)icmp + sizeof(IPv6Header), len - sizeof(IPv6Header)));
|
||||
}
|
||||
@ -102,8 +108,8 @@ inline void generate_echo_request(Buffer &buf,
|
||||
const IPv6::Addr &dest,
|
||||
const void *extra_data,
|
||||
const size_t extra_data_size,
|
||||
const unsigned int id,
|
||||
const unsigned int seq_num,
|
||||
const uint16_t id,
|
||||
const uint16_t seq_num,
|
||||
const size_t total_size,
|
||||
std::string *log_info)
|
||||
{
|
||||
@ -120,7 +126,7 @@ inline void generate_echo_request(Buffer &buf,
|
||||
icmp->head.flow_lbl[0] = 0;
|
||||
icmp->head.flow_lbl[1] = 0;
|
||||
icmp->head.flow_lbl[2] = 0;
|
||||
icmp->head.payload_len = htons(sizeof(ICMPv6) - sizeof(IPv6Header) + data_size);
|
||||
icmp->head.payload_len = htons(numeric_cast<uint16_t>(sizeof(ICMPv6) - sizeof(IPv6Header) + data_size));
|
||||
icmp->head.nexthdr = IPCommon::ICMPv6;
|
||||
icmp->head.hop_limit = 64;
|
||||
icmp->head.saddr = src.to_in6_addr();
|
||||
@ -167,5 +173,4 @@ inline void generate_echo_reply(Buffer &buf,
|
||||
if (log_info)
|
||||
*log_info = "ECHO6_REPLY size=" + std::to_string(buf.size()) + ' ' + IPv6::Addr::from_in6_addr(&icmp->head.saddr).to_string() + " -> " + IPv6::Addr::from_in6_addr(&icmp->head.daddr).to_string();
|
||||
}
|
||||
} // namespace Ping6
|
||||
} // namespace openvpn
|
||||
} // namespace openvpn::Ping6
|
@ -30,6 +30,7 @@
|
||||
#include <utility>
|
||||
#include <initializer_list>
|
||||
|
||||
#include <openvpn/common/numeric_cast.hpp>
|
||||
#include <openvpn/common/usergroup.hpp>
|
||||
|
||||
#ifndef OPENVPN_PLATFORM_LINUX
|
||||
@ -147,8 +148,8 @@ class SetUserGroupRetainCap : public SetUserGroup
|
||||
|
||||
void set_flag(const std::vector<cap_value_t> &caps)
|
||||
{
|
||||
if (::cap_set_flag(capabilities, CAP_PERMITTED, caps.size(), caps.data(), CAP_SET)
|
||||
|| ::cap_set_flag(capabilities, CAP_EFFECTIVE, caps.size(), caps.data(), CAP_SET))
|
||||
if (::cap_set_flag(capabilities, CAP_PERMITTED, numeric_cast<int>(caps.size()), caps.data(), CAP_SET)
|
||||
|| ::cap_set_flag(capabilities, CAP_EFFECTIVE, numeric_cast<int>(caps.size()), caps.data(), CAP_SET))
|
||||
{
|
||||
const int eno = errno;
|
||||
OPENVPN_THROW(user_group_err, "SetUserGroupRetainCap::Capabilities: cap_set_flag " << title << " fail: " << strerror_str(eno));
|
||||
|
@ -81,7 +81,7 @@ class LogPeriod
|
||||
return period_ != UNDEF;
|
||||
}
|
||||
|
||||
unsigned int expires_in(const time_t now)
|
||||
time_t expires_in(const time_t now)
|
||||
{
|
||||
const olong onow = olong(now);
|
||||
if (onow < end_)
|
||||
|
@ -27,4 +27,39 @@ TEST(misc, tempfile)
|
||||
tf.reset();
|
||||
const std::string s2 = tf.read();
|
||||
ASSERT_EQ(s2, content2);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(misc, tempfile_name)
|
||||
{
|
||||
TempFile tf(getTempDirPath("tempfile-XXXXXX"), true);
|
||||
auto fn = tf.filename();
|
||||
ASSERT_NE(std::string::npos, fn.find("tempfile-"));
|
||||
ASSERT_EQ(std::string::npos, fn.find("XXXXXX"));
|
||||
}
|
||||
|
||||
TEST(misc, tempfile_name_6Xs)
|
||||
{
|
||||
TempFile tf(getTempDirPath("tempXXXXXXfile"), true);
|
||||
auto fn = tf.filename();
|
||||
ASSERT_NE(std::string::npos, fn.find("temp"));
|
||||
ASSERT_NE(std::string::npos, fn.find("file"));
|
||||
ASSERT_EQ(std::string::npos, fn.find("XXXXXX"));
|
||||
}
|
||||
|
||||
TEST(misc, tempfile_name_7Xs)
|
||||
{
|
||||
TempFile tf(getTempDirPath("tempXXXXXXXfile"), true);
|
||||
auto fn = tf.filename();
|
||||
ASSERT_NE(std::string::npos, fn.find("temp"));
|
||||
ASSERT_NE(std::string::npos, fn.find("file"));
|
||||
ASSERT_EQ(std::string::npos, fn.find("XXXXXX"));
|
||||
}
|
||||
|
||||
TEST(misc, tempfile_name_6X6X)
|
||||
{
|
||||
TempFile tf(getTempDirPath("tempXXXXXXfile-XXXXXX"), true);
|
||||
auto fn = tf.filename();
|
||||
ASSERT_NE(std::string::npos, fn.find("temp"));
|
||||
ASSERT_NE(std::string::npos, fn.find("file"));
|
||||
ASSERT_EQ(fn.rfind("XXXXXX"), fn.find("XXXXXX"));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user