mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-28 08:59:37 -05:00
moved static/parsing of radix parts of short invites into RsCertificate (more code should be moved static there) and fixed adding incoming keys to friend server
This commit is contained in:
parent
5da31592f2
commit
b7c7c4c3f5
@ -28,6 +28,7 @@
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <util/radix64.h>
|
||||
#include <pgp/pgpkeyutil.h>
|
||||
#include <pgp/pgphandler.h>
|
||||
#include "rscertificate.h"
|
||||
#include "util/rsstring.h"
|
||||
#include "util/stacktrace.h"
|
||||
@ -621,6 +622,140 @@ bool RsCertificate::cleanRadix64(const std::string& instr,std::string& str,uint3
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool RsCertificate::decodeRadix64ShortInvite(const std::string& rsInvite, RsPeerDetails& details, uint32_t& err_code)
|
||||
{
|
||||
err_code = 0;
|
||||
std::vector<uint8_t> bf = Radix64::decode(rsInvite);
|
||||
size_t size = bf.size();
|
||||
|
||||
unsigned char* buf = bf.data();
|
||||
size_t total_s = 0;
|
||||
bool CRC_ok = false ; // not checked yet
|
||||
|
||||
while(total_s < size)
|
||||
{
|
||||
RsShortInviteFieldType ptag = RsShortInviteFieldType(buf[0]);
|
||||
buf = &buf[1];
|
||||
|
||||
unsigned char *buf2 = buf;
|
||||
uint32_t s = 0;
|
||||
|
||||
try { s = PGPKeyParser::read_125Size(buf); }
|
||||
catch (...)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
total_s += 1 + ( reinterpret_cast<size_t>(buf) - reinterpret_cast<size_t>(buf2) );
|
||||
|
||||
if(total_s > size)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: "
|
||||
<< static_cast<uint32_t>(ptag)
|
||||
<< ", size " << s << ", total_s = " << total_s
|
||||
<< ", expected total = " << size << std::endl;
|
||||
|
||||
switch(ptag)
|
||||
{
|
||||
case RsShortInviteFieldType::SSL_ID:
|
||||
details.id = RsPeerId::fromBufferUnsafe(buf) ;
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::PEER_NAME:
|
||||
details.name = std::string((char*)buf,s);
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::PGP_FINGERPRINT:
|
||||
details.fpr = RsPgpFingerprint::fromBufferUnsafe(buf);
|
||||
details.gpg_id = PGPHandler::pgpIdFromFingerprint(details.fpr);
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::LOCATOR:
|
||||
{
|
||||
std::string locatorStr((char*)buf,s);
|
||||
details.ipAddressList.push_back(locatorStr);
|
||||
}
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::DNS_LOCATOR:
|
||||
details.extPort = (((int)buf[0]) << 8) + buf[1];
|
||||
details.dyndns = std::string((char*)&buf[2],s-2);
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::LOC4_LOCATOR:
|
||||
{
|
||||
uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3];
|
||||
sockaddr_in tLocalAddr;
|
||||
tLocalAddr.sin_addr.s_addr = t4Addr;
|
||||
|
||||
details.localAddr = rs_inet_ntoa(tLocalAddr.sin_addr);
|
||||
details.localPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5];
|
||||
}
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::EXT4_LOCATOR:
|
||||
{
|
||||
uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3];
|
||||
sockaddr_in tExtAddr;
|
||||
tExtAddr.sin_addr.s_addr = t4Addr;
|
||||
|
||||
details.extAddr = rs_inet_ntoa(tExtAddr.sin_addr);
|
||||
details.extPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5];
|
||||
}
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::HIDDEN_LOCATOR:
|
||||
details.hiddenType = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3];
|
||||
details.hiddenNodePort = (((uint32_t)buf[4]) << 8)+ (uint32_t)buf[5];
|
||||
details.isHiddenNode = true;
|
||||
details.hiddenNodeAddress = std::string((char*)&buf[6],s-6);
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::CHECKSUM:
|
||||
{
|
||||
if(s != 3 || total_s+3 != size) // make sure the checksum is the last section
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION;
|
||||
return false;
|
||||
}
|
||||
uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(bf.data(),size-5);
|
||||
uint32_t certificate_crc = static_cast<uint32_t>( buf[0] + (buf[1] << 8) + (buf[2] << 16) );
|
||||
|
||||
if(computed_crc != certificate_crc)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR;
|
||||
return false;
|
||||
}
|
||||
CRC_ok = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
buf = &buf[s];
|
||||
total_s += s;
|
||||
}
|
||||
|
||||
if(details.id.isNull())
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_MISSING_LOCATION_ID;
|
||||
return false;
|
||||
}
|
||||
if(!CRC_ok)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -36,6 +36,21 @@ struct RsPeerDetails;
|
||||
class RsCertificate
|
||||
{
|
||||
public:
|
||||
enum class RsShortInviteFieldType : uint8_t
|
||||
{
|
||||
SSL_ID = 0x00,
|
||||
PEER_NAME = 0x01,
|
||||
LOCATOR = 0x02,
|
||||
PGP_FINGERPRINT = 0x03,
|
||||
CHECKSUM = 0x04,
|
||||
|
||||
/* The following will be deprecated, and ported to LOCATOR when generic transport layer will be implemented */
|
||||
HIDDEN_LOCATOR = 0x90,
|
||||
DNS_LOCATOR = 0x91,
|
||||
EXT4_LOCATOR = 0x92, // external IPv4 address
|
||||
LOC4_LOCATOR = 0x93 // local IPv4 address
|
||||
};
|
||||
|
||||
typedef enum { RS_CERTIFICATE_OLD_FORMAT, RS_CERTIFICATE_RADIX, RS_CERTIFICATE_SHORT_RADIX } Format;
|
||||
|
||||
/**
|
||||
@ -64,6 +79,8 @@ public:
|
||||
|
||||
~RsCertificate();
|
||||
|
||||
static bool decodeRadix64ShortInvite(const std::string& short_invite_b64,RsPeerDetails& det,uint32_t& error_code);
|
||||
|
||||
/// Convert to certificate radix string
|
||||
std::string toStdString() const;
|
||||
|
||||
|
@ -48,6 +48,7 @@
|
||||
|
||||
#include "pqi/authssl.h"
|
||||
|
||||
typedef RsCertificate::RsShortInviteFieldType RsShortInviteFieldType; // locally in this file to avoid renaming everything.
|
||||
|
||||
RsPeers *rsPeers = NULL;
|
||||
|
||||
@ -1159,22 +1160,6 @@ bool p3Peers::GetPGPBase64StringAndCheckSum(
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class RsShortInviteFieldType : uint8_t
|
||||
{
|
||||
SSL_ID = 0x00,
|
||||
PEER_NAME = 0x01,
|
||||
LOCATOR = 0x02,
|
||||
PGP_FINGERPRINT = 0x03,
|
||||
CHECKSUM = 0x04,
|
||||
|
||||
/* The following will be deprecated, and ported to LOCATOR when generic
|
||||
* trasport layer will be implemented */
|
||||
HIDDEN_LOCATOR = 0x90,
|
||||
DNS_LOCATOR = 0x91,
|
||||
EXT4_LOCATOR = 0x92, // external IPv4 address
|
||||
LOC4_LOCATOR = 0x93 // local IPv4 address
|
||||
};
|
||||
|
||||
static void addPacketHeader(RsShortInviteFieldType ptag, size_t size, unsigned char *& buf, uint32_t& offset, uint32_t& buf_size)
|
||||
{
|
||||
// Check that the buffer has sufficient size. If not, increase it.
|
||||
@ -1351,136 +1336,23 @@ bool p3Peers::getShortInvite(std::string& invite, const RsPeerId& _sslId, Retros
|
||||
|
||||
bool p3Peers::parseShortInvite(const std::string& inviteStrUrl, RsPeerDetails& details, uint32_t &err_code )
|
||||
{
|
||||
if(inviteStrUrl.empty())
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " can't parse empty invite"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
std::string rsInvite = inviteStrUrl;
|
||||
if(inviteStrUrl.empty())
|
||||
{
|
||||
RsErr() << __PRETTY_FUNCTION__ << " can't parse empty invite"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
std::string rsInvite = inviteStrUrl;
|
||||
|
||||
RsUrl inviteUrl(inviteStrUrl);
|
||||
RsUrl inviteUrl(inviteStrUrl);
|
||||
|
||||
if(inviteUrl.hasQueryK("rsInvite"))
|
||||
rsInvite = *inviteUrl.getQueryV("rsInvite");
|
||||
if(inviteUrl.hasQueryK("rsInvite"))
|
||||
rsInvite = *inviteUrl.getQueryV("rsInvite");
|
||||
|
||||
std::vector<uint8_t> bf = Radix64::decode(rsInvite);
|
||||
size_t size = bf.size();
|
||||
if(!RsCertificate::decodeRadix64ShortInvite(rsInvite, details, err_code))
|
||||
return false;
|
||||
|
||||
unsigned char* buf = bf.data();
|
||||
size_t total_s = 0;
|
||||
bool CRC_ok = false ; // not checked yet
|
||||
|
||||
while(total_s < size)
|
||||
{
|
||||
RsShortInviteFieldType ptag = RsShortInviteFieldType(buf[0]);
|
||||
buf = &buf[1];
|
||||
|
||||
unsigned char *buf2 = buf;
|
||||
uint32_t s = 0;
|
||||
|
||||
try { s = PGPKeyParser::read_125Size(buf); }
|
||||
catch (...)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
total_s += 1 + ( reinterpret_cast<size_t>(buf) - reinterpret_cast<size_t>(buf2) );
|
||||
|
||||
if(total_s > size)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
Dbg3() << __PRETTY_FUNCTION__ << " Read ptag: "
|
||||
<< static_cast<uint32_t>(ptag)
|
||||
<< ", size " << s << ", total_s = " << total_s
|
||||
<< ", expected total = " << size << std::endl;
|
||||
|
||||
switch(ptag)
|
||||
{
|
||||
case RsShortInviteFieldType::SSL_ID:
|
||||
details.id = RsPeerId::fromBufferUnsafe(buf) ;
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::PEER_NAME:
|
||||
details.name = std::string((char*)buf,s);
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::PGP_FINGERPRINT:
|
||||
details.fpr = RsPgpFingerprint::fromBufferUnsafe(buf);
|
||||
details.gpg_id = PGPHandler::pgpIdFromFingerprint(details.fpr);
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::LOCATOR:
|
||||
{
|
||||
std::string locatorStr((char*)buf,s);
|
||||
details.ipAddressList.push_back(locatorStr);
|
||||
}
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::DNS_LOCATOR:
|
||||
details.extPort = (((int)buf[0]) << 8) + buf[1];
|
||||
details.dyndns = std::string((char*)&buf[2],s-2);
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::LOC4_LOCATOR:
|
||||
{
|
||||
uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3];
|
||||
sockaddr_in tLocalAddr;
|
||||
tLocalAddr.sin_addr.s_addr = t4Addr;
|
||||
|
||||
details.localAddr = rs_inet_ntoa(tLocalAddr.sin_addr);
|
||||
details.localPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5];
|
||||
}
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::EXT4_LOCATOR:
|
||||
{
|
||||
uint32_t t4Addr = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3];
|
||||
sockaddr_in tExtAddr;
|
||||
tExtAddr.sin_addr.s_addr = t4Addr;
|
||||
|
||||
details.extAddr = rs_inet_ntoa(tExtAddr.sin_addr);
|
||||
details.extPort = (((uint32_t)buf[4])<<8) + (uint32_t)buf[5];
|
||||
}
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::HIDDEN_LOCATOR:
|
||||
details.hiddenType = (((uint32_t)buf[0]) << 24)+(((uint32_t)buf[1])<<16)+(((uint32_t)buf[2])<<8) + (uint32_t)buf[3];
|
||||
details.hiddenNodePort = (((uint32_t)buf[4]) << 8)+ (uint32_t)buf[5];
|
||||
details.isHiddenNode = true;
|
||||
details.hiddenNodeAddress = std::string((char*)&buf[6],s-6);
|
||||
break;
|
||||
|
||||
case RsShortInviteFieldType::CHECKSUM:
|
||||
{
|
||||
if(s != 3 || total_s+3 != size) // make sure the checksum is the last section
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION;
|
||||
return false;
|
||||
}
|
||||
uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(bf.data(),size-5);
|
||||
uint32_t certificate_crc = static_cast<uint32_t>( buf[0] + (buf[1] << 8) + (buf[2] << 16) );
|
||||
|
||||
if(computed_crc != certificate_crc)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR;
|
||||
return false;
|
||||
}
|
||||
CRC_ok = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
buf = &buf[s];
|
||||
total_s += s;
|
||||
}
|
||||
|
||||
// now check if the PGP key is available. If so, add it in the PeerDetails:
|
||||
// Also check if the PGP key is available. If so, add it in the PeerDetails:
|
||||
|
||||
RsPeerDetails pgp_det ;
|
||||
if(getGPGDetails(PGPHandler::pgpIdFromFingerprint(details.fpr),pgp_det) && pgp_det.fpr == details.fpr)
|
||||
@ -1497,23 +1369,13 @@ bool p3Peers::parseShortInvite(const std::string& inviteStrUrl, RsPeerDetails& d
|
||||
else
|
||||
details.skip_pgp_signature_validation = true;
|
||||
|
||||
if(!CRC_ok)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(details.gpg_id.isNull())
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_MISSING_PGP_FINGERPRINT;
|
||||
return false;
|
||||
}
|
||||
if(details.id.isNull())
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_MISSING_LOCATION_ID;
|
||||
return false;
|
||||
}
|
||||
err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR;
|
||||
return true;
|
||||
err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3Peers::acceptInvite( const std::string& invite,
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "util/rsbase64.h"
|
||||
#include "util/radix64.h"
|
||||
|
||||
#include "pgp/rscertificate.h"
|
||||
|
||||
#include "friendserver.h"
|
||||
#include "friend_server/fsitem.h"
|
||||
|
||||
@ -92,7 +94,7 @@ void FriendServer::handleClientPublish(const RsFriendServerClientPublishItem *it
|
||||
RsPeerDetails shortInviteDetails;
|
||||
uint32_t errorCode = 0;
|
||||
|
||||
if(item->short_invite.empty() || !rsPeers->parseShortInvite(item->short_invite, shortInviteDetails,errorCode ))
|
||||
if(item->short_invite.empty() || !RsCertificate::decodeRadix64ShortInvite(item->short_invite, shortInviteDetails,errorCode ))
|
||||
throw std::runtime_error("Could not parse short certificate. Error = " + RsUtil::NumberToString(errorCode));
|
||||
|
||||
RsDbg() << " Short invite is fine. PGP fingerprint: " << shortInviteDetails.fpr ;
|
||||
|
Loading…
Reference in New Issue
Block a user