Browse Source

verify jump link for valid characters

pull/1982/head
orignal 1 year ago
parent
commit
3286bdb4a7
  1. 12
      libi2pd/Base.cpp
  2. 4
      libi2pd/Base.h
  3. 18
      libi2pd_client/AddressBook.cpp
  4. 35
      libi2pd_client/HTTPProxy.cpp

12
libi2pd/Base.cpp

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2022, The PurpleI2P Project * Copyright (c) 2013-2023, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -28,6 +28,11 @@ namespace data
return T32; return T32;
} }
bool IsBase32 (char ch)
{
return (ch >= 'a' && ch <= 'z') || (ch >= '2' && ch <= '7');
}
static void iT64Build(void); static void iT64Build(void);
/* /*
@ -55,6 +60,11 @@ namespace data
return T64; return T64;
} }
bool IsBase64 (char ch)
{
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '-' || ch == '~';
}
/* /*
* Reverse Substitution Table (built in run time) * Reverse Substitution Table (built in run time)
*/ */

4
libi2pd/Base.h

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2020, The PurpleI2P Project * Copyright (c) 2013-2023, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -19,9 +19,11 @@ namespace data {
size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len ); size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len );
const char * GetBase32SubstitutionTable (); const char * GetBase32SubstitutionTable ();
const char * GetBase64SubstitutionTable (); const char * GetBase64SubstitutionTable ();
bool IsBase64 (char ch);
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
bool IsBase32 (char ch);
/** /**
* Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes * Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes

18
libi2pd_client/AddressBook.cpp

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2022, The PurpleI2P Project * Copyright (c) 2013-2023, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@ -403,9 +403,19 @@ namespace client
if (!addr) if (!addr)
return false; return false;
i2p::data::IdentityEx ident; auto pos = jump.find(".b32.i2p");
if (ident.FromBase64 (jump) && ident.GetIdentHash () == addr->identHash) if (pos != std::string::npos)
return true; {
i2p::data::IdentHash identHash;
if (identHash.FromBase32(jump.substr (0, pos)) && identHash == addr->identHash)
return true;
}
else
{
i2p::data::IdentityEx ident;
if (ident.FromBase64 (jump) && ident.GetIdentHash () == addr->identHash)
return true;
}
return false; return false;
} }

35
libi2pd_client/HTTPProxy.cpp

@ -75,8 +75,9 @@ namespace proxy {
void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered); void HandleSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered);
void Terminate(); void Terminate();
void AsyncSockRead(); void AsyncSockRead();
bool ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm); static bool ExtractAddressHelper(i2p::http::URL& url, std::string& jump, bool& confirm);
void SanitizeHTTPRequest(i2p::http::HTTPReq & req); static bool VerifyAddressHelper (const std::string& jump);
static void SanitizeHTTPRequest(i2p::http::HTTPReq& req);
void SentHTTPFailed(const boost::system::error_code & ecode); void SentHTTPFailed(const boost::system::error_code & ecode);
void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream); void HandleStreamRequestComplete (std::shared_ptr<i2p::stream::Stream> stream);
/* error helpers */ /* error helpers */
@ -221,7 +222,7 @@ namespace proxy {
std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1)); std::bind(&HTTPReqHandler::SentHTTPFailed, shared_from_this(), std::placeholders::_1));
} }
bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL & url, std::string & b64, bool & confirm) bool HTTPReqHandler::ExtractAddressHelper(i2p::http::URL& url, std::string& jump, bool& confirm)
{ {
confirm = false; confirm = false;
const char *param = "i2paddresshelper="; const char *param = "i2paddresshelper=";
@ -237,7 +238,12 @@ namespace proxy {
std::string value = params["i2paddresshelper"]; std::string value = params["i2paddresshelper"];
len += value.length(); len += value.length();
b64 = i2p::http::UrlDecode(value); jump = i2p::http::UrlDecode(value);
if (!VerifyAddressHelper (jump))
{
LogPrint (eLogError, "HTTPProxy: Malformed jump link ", jump);
return false;
}
// if we need update exists, request formed with update param // if we need update exists, request formed with update param
if (params["update"] == "true") if (params["update"] == "true")
@ -269,7 +275,26 @@ namespace proxy {
return true; return true;
} }
void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq & req) bool HTTPReqHandler::VerifyAddressHelper (const std::string& jump)
{
auto pos = jump.find(".b32.i2p");
if (pos != std::string::npos)
{
auto b32 = jump.substr (0, pos);
for (auto& ch: b32)
if (!i2p::data::IsBase32(ch)) return false;
return true;
}
else
{
for (auto& ch: jump)
if (!i2p::data::IsBase64(ch)) return false;
return true;
}
return false;
}
void HTTPReqHandler::SanitizeHTTPRequest(i2p::http::HTTPReq& req)
{ {
/* drop common headers */ /* drop common headers */
req.RemoveHeader("Via"); req.RemoveHeader("Via");

Loading…
Cancel
Save