Fix crash in p3Peers::loadCertificateFromString

This function is part of the public API so it must be safe to call with
any input, before this commit if would crash if feeded with a broken or
empty certificate radix string.
This commit is contained in:
Gioacchino Mazzurco 2018-10-12 22:28:44 +02:00
parent fc14300b06
commit 15b729b35c
No known key found for this signature in database
GPG Key ID: A1FBCA3872E87051
3 changed files with 113 additions and 65 deletions

View File

@ -30,6 +30,7 @@
#include <pgp/pgpkeyutil.h> #include <pgp/pgpkeyutil.h>
#include "rscertificate.h" #include "rscertificate.h"
#include "util/rsstring.h" #include "util/rsstring.h"
#include "util/stacktrace.h"
//#define DEBUG_RSCERTIFICATE //#define DEBUG_RSCERTIFICATE
@ -88,6 +89,17 @@ void RsCertificate::addPacket(uint8_t ptag, const unsigned char *mem, size_t siz
offset += size ; offset += size ;
} }
const RsCertificate&RsCertificate::operator=(const RsCertificate&)
{
memset(ipv4_external_ip_and_port,0,6);
memset(ipv4_internal_ip_and_port,0,6);
binary_pgp_key = nullptr;
binary_pgp_key_size = 0;
only_pgp = false;
hidden_node = false;
return *this;
}
std::string RsCertificate::toStdString() const std::string RsCertificate::toStdString() const
{ {
//std::string res ; //std::string res ;
@ -154,17 +166,21 @@ std::string RsCertificate::toStdString() const
return out2 ; return out2 ;
} }
RsCertificate::RsCertificate(const std::string& str) RsCertificate::RsCertificate(const std::string& str) :
: location_name(""), pgp_version("Version: OpenPGP:SDK v0.9"),
location_name(""), dns_name(""), only_pgp(true)
pgp_version("Version: OpenPGP:SDK v0.9"),
dns_name(""),only_pgp(true)
{ {
uint32_t err_code ; uint32_t err_code;
binary_pgp_key = NULL ; binary_pgp_key = nullptr;
if(!initFromString(str,err_code)) if(!initializeFromString(str, err_code))
throw err_code ; {
std::cerr << __PRETTY_FUNCTION__ << " is deprecated because it can "
<< "miserably fail like this! str: " << str
<< " err_code: " << err_code << std::endl;
print_stacktrace();
throw err_code;
}
} }
RsCertificate::RsCertificate(const RsPeerDetails& Detail, const unsigned char *binary_pgp_block,size_t binary_pgp_block_size) RsCertificate::RsCertificate(const RsPeerDetails& Detail, const unsigned char *binary_pgp_block,size_t binary_pgp_block_size)
@ -256,7 +272,7 @@ void RsCertificate::scan_ip(const std::string& ip_string, unsigned short port,un
ip_and_port[5] = port & 0xff ; ip_and_port[5] = port & 0xff ;
} }
bool RsCertificate::initFromString(const std::string& instr,uint32_t& err_code) bool RsCertificate::initializeFromString(const std::string& instr,uint32_t& err_code)
{ {
try try
{ {

View File

@ -51,72 +51,94 @@ struct RsPeerDetails;
class RsCertificate class RsCertificate
{ {
public: public:
typedef enum { RS_CERTIFICATE_OLD_FORMAT, RS_CERTIFICATE_RADIX } Format ; typedef enum { RS_CERTIFICATE_OLD_FORMAT, RS_CERTIFICATE_RADIX } Format;
// Constructs from text. /**
// - new format: The input string should only contain radix chars and spaces/LF/tabs. * @brief Costruct an empty certificate, use toghether with
// * if(initializeFromString) for safe certificate radix string parsing
explicit RsCertificate(const std::string& input_string) ; */
RsCertificate() :
ipv4_external_ip_and_port{0,0,0,0,0,0},
ipv4_internal_ip_and_port{0,0,0,0,0,0},
binary_pgp_key(nullptr), binary_pgp_key_size(0),
pgp_version("Version: OpenPGP:SDK v0.9"), only_pgp(true),
hidden_node(false) {}
// Constructs from binary gpg key, and RsPeerDetails. /**
// * @brief Initialize from certificate string
RsCertificate(const RsPeerDetails& details,const unsigned char *gpg_mem_block,size_t gpg_mem_block_size) ; * @param[in] str radix format string
* @param[out] errCode storage for eventual error code
* @return false on failure, true otherwise
*/
bool initializeFromString(const std::string& str, uint32_t& errCode);
// Constructs /// Constructs from binary gpg key, and RsPeerDetails.
RsCertificate( const RsPeerDetails& details,
const unsigned char *gpg_mem_block,
size_t gpg_mem_block_size );
virtual ~RsCertificate(); virtual ~RsCertificate();
// Outut to text /// Convert to certificate radix string
std::string toStdString() const ; std::string toStdString() const;
std::string ext_ip_string() const ; std::string ext_ip_string() const;
std::string loc_ip_string() const ; std::string loc_ip_string() const;
std::string location_name_string() const { return location_name; } std::string location_name_string() const { return location_name; }
std::string dns_string() const { return dns_name ; } std::string dns_string() const { return dns_name ; }
RsPeerId sslid() const { return location_id ; } RsPeerId sslid() const { return location_id ; }
std::string hidden_node_string() const; std::string hidden_node_string() const;
std::string armouredPGPKey() const ; std::string armouredPGPKey() const;
unsigned short ext_port_us() const ; unsigned short ext_port_us() const;
unsigned short loc_port_us() const ; unsigned short loc_port_us() const;
const unsigned char *pgp_key() const { return binary_pgp_key ; } const unsigned char *pgp_key() const { return binary_pgp_key ; }
size_t pgp_key_size() const { return binary_pgp_key_size ; } size_t pgp_key_size() const { return binary_pgp_key_size ; }
static bool cleanCertificate(const std::string& input, std::string& output, RsCertificate::Format& format, int& error_code, bool check_content) ; static bool cleanCertificate(
const std::string& input, std::string& output,
RsCertificate::Format& format, int& error_code, bool check_content);
const std::set<RsUrl>& locators() const { return mLocators; } const std::set<RsUrl>& locators() const { return mLocators; }
private: /**
static bool cleanCertificate(const std::string& input,std::string& output,int&) ; // new radix format * @deprecated using this costructor may raise exception that cause
static void scan_ip(const std::string& ip_string, unsigned short port,unsigned char *destination_memory) ; * crash if not handled, use empty constructor + if(initFromString) for a
* safer behaviour.
*/
RS_DEPRECATED explicit RsCertificate(const std::string& input_string);
bool initFromString(const std::string& str,uint32_t& err_code) ; private:
// new radix format
static bool cleanCertificate( const std::string& input,
std::string& output, int&);
static void addPacket(uint8_t ptag, const unsigned char *mem, size_t size, unsigned char *& buf, size_t& offset, size_t& buf_size) ; static void scan_ip( const std::string& ip_string, unsigned short port,
unsigned char *destination_memory );
RsCertificate(const RsCertificate&) {} // non copy-able static void addPacket(uint8_t ptag, const unsigned char *mem, size_t size,
const RsCertificate& operator=(const RsCertificate&) unsigned char*& buf, size_t& offset, size_t& buf_size);
{ memset(ipv4_external_ip_and_port,0,6); memset(ipv4_internal_ip_and_port,0,6);
binary_pgp_key = NULL; binary_pgp_key_size = 0;
only_pgp = false; hidden_node = false;
return *this ;} // non copy-able
unsigned char ipv4_external_ip_and_port[6] ; RsCertificate(const RsCertificate&) {} /// non copy-able
unsigned char ipv4_internal_ip_and_port[6] ; const RsCertificate& operator=(const RsCertificate&); /// non copy-able
unsigned char *binary_pgp_key ; unsigned char ipv4_external_ip_and_port[6];
size_t binary_pgp_key_size ; unsigned char ipv4_internal_ip_and_port[6];
std::string location_name ; unsigned char *binary_pgp_key;
RsPeerId location_id ; size_t binary_pgp_key_size;
std::string pgp_version ;
std::string dns_name ; std::string location_name;
RsPeerId location_id;
std::string pgp_version;
std::string dns_name;
std::string hidden_node_address; std::string hidden_node_address;
std::set<RsUrl> mLocators; std::set<RsUrl> mLocators;
bool only_pgp ; // does the cert contain only pgp info? bool only_pgp ; /// does the cert contain only pgp info?
bool hidden_node; // IP or hidden Node Address. bool hidden_node; /// IP or hidden Node Address.
}; };

View File

@ -1213,17 +1213,27 @@ std::string p3Peers::GetRetroshareInvite(
//=========================================================================== //===========================================================================
bool p3Peers::loadCertificateFromString(const std::string& cert, RsPeerId& ssl_id, RsPgpId& gpg_id, std::string& error_string) bool p3Peers::loadCertificateFromString(
const std::string& cert, RsPeerId& ssl_id,
RsPgpId& gpg_id, std::string& error_string )
{ {
RsCertificate crt(cert) ; RsCertificate crt;
RsPgpId gpgid ; uint32_t errNum = 0;
if(!crt.initializeFromString(cert,errNum))
{
error_string = "RsCertificate failed with errno: "
+ std::to_string(errNum) + " parsing: " + cert;
return false;
}
bool res = AuthGPG::getAuthGPG()->LoadCertificateFromString(crt.armouredPGPKey(),gpgid,error_string) ; RsPgpId gpgid;
bool res = AuthGPG::getAuthGPG()->
LoadCertificateFromString(crt.armouredPGPKey(), gpgid,error_string);
gpg_id = gpgid; gpg_id = gpgid;
ssl_id = crt.sslid() ; ssl_id = crt.sslid();
return res ; return res;
} }
bool p3Peers::loadDetailsFromStringCert( const std::string &certstr, bool p3Peers::loadDetailsFromStringCert( const std::string &certstr,