mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-02-23 16:30:06 -05:00
- made errors of certificate (new formaT) parsing translatable.
- added checksum code for new format certificate. Will be enabled in v0.6, since it is not backward compatible - fixed very stupid bug in radix64 cleaning function, causing any certificate to be accepted as a radix string - added list of non backward compatible changes in README.txt, so that we can track them git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@6030 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
0f26b85a88
commit
d893d30883
@ -1,4 +1,4 @@
|
||||
To use this branch:
|
||||
To compile:
|
||||
|
||||
- get source code for libssh-0.5.2, unzip it, and create build directory (if needed)
|
||||
|
||||
@ -36,3 +36,8 @@ To use this branch:
|
||||
|
||||
and use the command line interface to control your RS instance.
|
||||
|
||||
List of non backward compatible changes for V0.6:
|
||||
================================================
|
||||
|
||||
- in rscertificate.cc, enable V_06_USE_CHECKSUM
|
||||
- in p3charservice, remove all usage of _deprecated items
|
||||
|
@ -8,7 +8,9 @@
|
||||
#include <pgp/pgpkeyutil.h>
|
||||
#include "rscertificate.h"
|
||||
|
||||
#define DEBUG_RSCERTIFICATE
|
||||
//#define DEBUG_RSCERTIFICATE
|
||||
|
||||
//#define V_06_USE_CHECKSUM
|
||||
|
||||
static const std::string PGP_CERTIFICATE_START ( "-----BEGIN PGP PUBLIC KEY BLOCK-----" );
|
||||
static const std::string PGP_CERTIFICATE_END ( "-----END PGP PUBLIC KEY BLOCK-----" );
|
||||
@ -23,10 +25,11 @@ static const uint8_t CERTIFICATE_PTAG_LOCIPANDPORT_SECTION = 0x03 ;
|
||||
static const uint8_t CERTIFICATE_PTAG_DNS_SECTION = 0x04 ;
|
||||
static const uint8_t CERTIFICATE_PTAG_SSLID_SECTION = 0x05 ;
|
||||
static const uint8_t CERTIFICATE_PTAG_NAME_SECTION = 0x06 ;
|
||||
static const uint8_t CERTIFICATE_PTAG_CHECKSUM_SECTION = 0x07 ;
|
||||
|
||||
static bool is_acceptable_radix64Char(char c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '/' || '=' ;
|
||||
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '/' || c == '=' ;
|
||||
}
|
||||
|
||||
RsCertificate::~RsCertificate()
|
||||
@ -80,7 +83,17 @@ std::string RsCertificate::toStdString() const
|
||||
addPacket( CERTIFICATE_PTAG_NAME_SECTION , (unsigned char *)location_name.c_str() ,location_name.length() , buf, p, BS ) ;
|
||||
addPacket( CERTIFICATE_PTAG_SSLID_SECTION , location_id.toByteArray() ,location_id.SIZE_IN_BYTES, buf, p, BS ) ;
|
||||
}
|
||||
#ifdef V_06_USE_CHECKSUM
|
||||
uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC(buf,p) ;
|
||||
|
||||
// handle endian issues.
|
||||
unsigned char mem[3] ;
|
||||
mem[0] = computed_crc & 0xff ;
|
||||
mem[1] = (computed_crc >> 8 ) & 0xff ;
|
||||
mem[2] = (computed_crc >> 16) & 0xff ;
|
||||
|
||||
addPacket( CERTIFICATE_PTAG_CHECKSUM_SECTION,mem,3,buf,p,BS) ;
|
||||
#endif
|
||||
std::string out_string ;
|
||||
|
||||
Radix64::encode((char *)buf, p, out_string) ;
|
||||
@ -108,10 +121,10 @@ RsCertificate::RsCertificate(const std::string& str)
|
||||
pgp_version("Version: OpenPGP:SDK v0.9"),
|
||||
dns_name(""),only_pgp(true)
|
||||
{
|
||||
std::string err_string ;
|
||||
uint32_t err_code ;
|
||||
|
||||
if(!initFromString(str,err_string) && !initFromString_oldFormat(str,err_string))
|
||||
throw std::runtime_error(err_string) ;
|
||||
if(!initFromString(str,err_code) && !initFromString_oldFormat(str,err_code))
|
||||
throw err_code ;
|
||||
}
|
||||
|
||||
RsCertificate::RsCertificate(const RsPeerDetails& Detail, const unsigned char *binary_pgp_block,size_t binary_pgp_block_size)
|
||||
@ -162,9 +175,10 @@ void RsCertificate::scan_ip(const std::string& ip_string, unsigned short port,un
|
||||
ip_and_port[5] = port & 0xff ;
|
||||
}
|
||||
|
||||
bool RsCertificate::initFromString(const std::string& instr,std::string& err_string)
|
||||
bool RsCertificate::initFromString(const std::string& instr,uint32_t& err_code)
|
||||
{
|
||||
std::string str ;
|
||||
err_code = CERTIFICATE_PARSING_ERROR_NO_ERROR ;
|
||||
|
||||
// 0 - clean the string and check that it is pure radix64
|
||||
//
|
||||
@ -179,7 +193,7 @@ bool RsCertificate::initFromString(const std::string& instr,std::string& err_str
|
||||
str += instr[i] ;
|
||||
}
|
||||
#ifdef DEBUG_RSCERTIFICATE
|
||||
std::cerr << "Decodign from:" << str << std::endl;
|
||||
std::cerr << "Decoding from:" << str << std::endl;
|
||||
#endif
|
||||
// 1 - decode the string.
|
||||
//
|
||||
@ -187,6 +201,7 @@ bool RsCertificate::initFromString(const std::string& instr,std::string& err_str
|
||||
size_t size ;
|
||||
Radix64::decode(str,bf, size) ;
|
||||
|
||||
bool checksum_check_passed = false ;
|
||||
unsigned char *buf = (unsigned char *)bf ;
|
||||
size_t total_s = 0 ;
|
||||
only_pgp = true ;
|
||||
@ -203,7 +218,7 @@ bool RsCertificate::initFromString(const std::string& instr,std::string& err_str
|
||||
|
||||
if(total_s > size)
|
||||
{
|
||||
err_string = "Abnormal size read. Bigger than memory block." ;
|
||||
err_code = CERTIFICATE_PARSING_ERROR_SIZE_ERROR ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
@ -225,7 +240,7 @@ bool RsCertificate::initFromString(const std::string& instr,std::string& err_str
|
||||
case CERTIFICATE_PTAG_SSLID_SECTION:
|
||||
if(s != location_id.SIZE_IN_BYTES)
|
||||
{
|
||||
err_string = "Inconsistent size in certificate section 'location ID'" ;
|
||||
err_code = CERTIFICATE_PARSING_ERROR_INVALID_LOCATION_ID ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
@ -241,7 +256,7 @@ bool RsCertificate::initFromString(const std::string& instr,std::string& err_str
|
||||
case CERTIFICATE_PTAG_LOCIPANDPORT_SECTION:
|
||||
if(s != 6)
|
||||
{
|
||||
err_string = "Inconsistent size in certificate section 'external IP'" ;
|
||||
err_code = CERTIFICATE_PARSING_ERROR_INVALID_LOCAL_IP;
|
||||
return false ;
|
||||
}
|
||||
|
||||
@ -251,20 +266,49 @@ bool RsCertificate::initFromString(const std::string& instr,std::string& err_str
|
||||
case CERTIFICATE_PTAG_EXTIPANDPORT_SECTION:
|
||||
if(s != 6)
|
||||
{
|
||||
err_string = "Inconsistent size in certificate section 'external IP'" ;
|
||||
err_code = CERTIFICATE_PARSING_ERROR_INVALID_EXTERNAL_IP;
|
||||
return false ;
|
||||
}
|
||||
|
||||
memcpy(ipv4_external_ip_and_port,buf,s) ;
|
||||
buf = &buf[s] ;
|
||||
break ;
|
||||
case CERTIFICATE_PTAG_CHECKSUM_SECTION:
|
||||
{
|
||||
if(s != 3 || total_s+3 != size)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION ;
|
||||
return false ;
|
||||
}
|
||||
uint32_t computed_crc = PGPKeyManagement::compute24bitsCRC((unsigned char *)bf,size-5) ;
|
||||
uint32_t certificate_crc = buf[0] + (buf[1] << 8) + (buf[2] << 16) ;
|
||||
|
||||
if(computed_crc != certificate_crc)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR ;
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
checksum_check_passed = true ;
|
||||
}
|
||||
break ;
|
||||
default:
|
||||
err_string = "Cannot read certificate. Parsing error in binary packets." ;
|
||||
err_code = CERTIFICATE_PARSING_ERROR_UNKNOWN_SECTION_PTAG ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
total_s += s ;
|
||||
}
|
||||
#ifdef V_06_USE_CHECKSUM
|
||||
if(!checksum_check_passed)
|
||||
{
|
||||
err_code = CERTIFICATE_PARSING_ERROR_MISSING_CHECKSUM ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(total_s != size)
|
||||
std::cerr << "(EE) Certificate contains trailing characters. Weird." << std::endl;
|
||||
|
||||
delete[] bf ;
|
||||
return true ;
|
||||
@ -755,7 +799,7 @@ std::string RsCertificate::toStdString_oldFormat() const
|
||||
return res ;
|
||||
}
|
||||
|
||||
bool RsCertificate::initFromString_oldFormat(const std::string& certstr,std::string& err_string)
|
||||
bool RsCertificate::initFromString_oldFormat(const std::string& certstr,uint32_t& err_code)
|
||||
{
|
||||
//parse the text to get ip address
|
||||
try
|
||||
|
@ -51,8 +51,8 @@ class RsCertificate
|
||||
static bool cleanCertificate_oldFormat(const std::string& input,std::string& output,int&) ; // old text format
|
||||
static void scan_ip(const std::string& ip_string, unsigned short port,unsigned char *destination_memory) ;
|
||||
|
||||
bool initFromString(const std::string& str,std::string& err_string) ;
|
||||
bool initFromString_oldFormat(const std::string& str,std::string& err_string) ;
|
||||
bool initFromString(const std::string& str,uint32_t& err_code) ;
|
||||
bool initFromString_oldFormat(const std::string& str,uint32_t& err_code) ;
|
||||
|
||||
static void addPacket(uint8_t ptag, const unsigned char *mem, size_t size, unsigned char *& buf, size_t& offset, size_t& buf_size) ;
|
||||
|
||||
|
@ -83,7 +83,8 @@ const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_UDP = 5;
|
||||
const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_TUNNEL = 6;
|
||||
const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN = 7;
|
||||
|
||||
/* Error codes for certificate cleaning */
|
||||
/* Error codes for certificate cleaning and cert parsing. Numbers should not overlap. */
|
||||
|
||||
const int RS_PEER_CERT_CLEANING_CODE_NO_ERROR = 0x00 ;
|
||||
const int RS_PEER_CERT_CLEANING_CODE_UNKOWN_ERROR = 0x01 ;
|
||||
const int RS_PEER_CERT_CLEANING_CODE_NO_BEGIN_TAG = 0x02 ;
|
||||
@ -92,6 +93,16 @@ const int RS_PEER_CERT_CLEANING_CODE_NO_CHECKSUM = 0x04 ;
|
||||
const int RS_PEER_CERT_CLEANING_CODE_WRONG_NUMBER = 0x05 ;
|
||||
const int RS_PEER_CERT_CLEANING_CODE_WRONG_RADIX_CHAR = 0x06 ;
|
||||
|
||||
const uint32_t CERTIFICATE_PARSING_ERROR_NO_ERROR = 0x10 ;
|
||||
const uint32_t CERTIFICATE_PARSING_ERROR_SIZE_ERROR = 0x11 ;
|
||||
const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_LOCATION_ID = 0x12 ;
|
||||
const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_EXTERNAL_IP = 0x13 ;
|
||||
const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_LOCAL_IP = 0x14 ;
|
||||
const uint32_t CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION = 0x15 ;
|
||||
const uint32_t CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR = 0x16 ;
|
||||
const uint32_t CERTIFICATE_PARSING_ERROR_UNKNOWN_SECTION_PTAG = 0x17 ;
|
||||
const uint32_t CERTIFICATE_PARSING_ERROR_MISSING_CHECKSUM = 0x18 ;
|
||||
|
||||
/* LinkType Flags */
|
||||
|
||||
// CONNECTION
|
||||
@ -131,6 +142,7 @@ const uint32_t RS_NET_CONN_TYPE_FRIEND = 0x02000000;
|
||||
const uint32_t RS_NET_CONN_TYPE_SERVER = 0x04000000;
|
||||
const uint32_t RS_NET_CONN_TYPE_CLIENT = 0x08000000;
|
||||
|
||||
// Potential certificate parsing errors.
|
||||
|
||||
|
||||
/* Groups */
|
||||
@ -288,7 +300,7 @@ class RsPeers
|
||||
virtual bool loadCertificateFromString(const std::string &cert, std::string &ssl_id, std::string &gpg_id) = 0;
|
||||
|
||||
// Gets the GPG details, but does not add the key to the keyring.
|
||||
virtual bool loadDetailsFromStringCert(const std::string& certGPG, RsPeerDetails &pd,std::string& error_string) = 0;
|
||||
virtual bool loadDetailsFromStringCert(const std::string& certGPG, RsPeerDetails &pd,uint32_t& error_code) = 0;
|
||||
|
||||
virtual bool cleanCertificate(const std::string &certstr, std::string &cleanCert,int& error_code) = 0;
|
||||
virtual bool saveCertificateToFile(const std::string &id, const std::string &fname) = 0;
|
||||
|
@ -905,7 +905,7 @@ bool p3Peers::loadCertificateFromFile(const std::string &/*fname*/, std::string
|
||||
return false;
|
||||
}
|
||||
|
||||
bool p3Peers::loadDetailsFromStringCert(const std::string &certstr, RsPeerDetails &pd,std::string& /*error_string*/)
|
||||
bool p3Peers::loadDetailsFromStringCert(const std::string &certstr, RsPeerDetails &pd,uint32_t& error_code)
|
||||
{
|
||||
#ifdef P3PEERS_DEBUG
|
||||
std::cerr << "p3Peers::LoadCertificateFromString() ";
|
||||
@ -932,9 +932,10 @@ bool p3Peers::loadDetailsFromStringCert(const std::string &certstr, RsPeerDetai
|
||||
pd.isOnlyGPGdetail = pd.id.empty();
|
||||
pd.service_perm_flags = RS_SERVICE_PERM_ALL ;
|
||||
}
|
||||
catch (...)
|
||||
catch(uint32_t e)
|
||||
{
|
||||
std::cerr << "ConnectFriendWizard : Parse ip address error." << std::endl;
|
||||
std::cerr << "ConnectFriendWizard : Parse ip address error :" << e << std::endl;
|
||||
error_code = e;
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ virtual bool hasExportMinimal() ;
|
||||
virtual bool loadCertificateFromFile(const std::string &fname, std::string &id, std::string &gpg_id);
|
||||
virtual bool loadCertificateFromString(const std::string& cert, std::string &id, std::string &gpg_id);
|
||||
|
||||
virtual bool loadDetailsFromStringCert(const std::string &cert, RsPeerDetails &pd, std::string& error_string);
|
||||
virtual bool loadDetailsFromStringCert(const std::string &cert, RsPeerDetails &pd, uint32_t& error_code);
|
||||
|
||||
virtual bool cleanCertificate(const std::string &certstr, std::string &cleanCert,int& error_code);
|
||||
virtual bool saveCertificateToFile(const std::string &id, const std::string &fname);
|
||||
|
@ -96,6 +96,24 @@ ConnectFriendWizard::ConnectFriendWizard(QWidget *parent) :
|
||||
ui->rsidRadioButton->hide();
|
||||
}
|
||||
|
||||
QString ConnectFriendWizard::getErrorString(uint32_t error_code)
|
||||
{
|
||||
switch(error_code)
|
||||
{
|
||||
case CERTIFICATE_PARSING_ERROR_SIZE_ERROR: return tr("Abnormal size read is bigger than memory block.") ;
|
||||
case CERTIFICATE_PARSING_ERROR_INVALID_LOCATION_ID: return tr("Invalid location id.") ;
|
||||
case CERTIFICATE_PARSING_ERROR_INVALID_EXTERNAL_IP: return tr("Invalid external IP.") ;
|
||||
case CERTIFICATE_PARSING_ERROR_INVALID_LOCAL_IP: return tr("Invalid local IP.") ;
|
||||
case CERTIFICATE_PARSING_ERROR_INVALID_CHECKSUM_SECTION: return tr("Invalid checksum section.") ;
|
||||
case CERTIFICATE_PARSING_ERROR_CHECKSUM_ERROR: return tr("Checksum mismatch. Certificate is corrupted.") ;
|
||||
case CERTIFICATE_PARSING_ERROR_UNKNOWN_SECTION_PTAG: return tr("Unknown section type found (Certificate might be corrupted).") ;
|
||||
case CERTIFICATE_PARSING_ERROR_MISSING_CHECKSUM: return tr("Missing checksum.") ;
|
||||
|
||||
default:
|
||||
return tr("Unknown certificate error") ;
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectFriendWizard::setCertificate(const QString &certificate, bool friendRequest)
|
||||
{
|
||||
if (certificate.isEmpty()) {
|
||||
@ -103,9 +121,9 @@ void ConnectFriendWizard::setCertificate(const QString &certificate, bool friend
|
||||
return;
|
||||
}
|
||||
|
||||
std::string error_string;
|
||||
uint32_t cert_load_error_code;
|
||||
|
||||
if (rsPeers->loadDetailsFromStringCert(certificate.toUtf8().constData(), peerDetails, error_string))
|
||||
if (rsPeers->loadDetailsFromStringCert(certificate.toUtf8().constData(), peerDetails, cert_load_error_code))
|
||||
{
|
||||
#ifdef FRIEND_WIZARD_DEBUG
|
||||
std::cerr << "ConnectFriendWizard got id : " << peerDetails.id << "; gpg_id : " << peerDetails.gpg_id << std::endl;
|
||||
@ -114,7 +132,7 @@ void ConnectFriendWizard::setCertificate(const QString &certificate, bool friend
|
||||
setStartId(friendRequest ? Page_FriendRequest : Page_Conclusion);
|
||||
} else {
|
||||
// error message
|
||||
setField("errorMessage", tr("Certificate Load Failed") + ": " + QString::fromUtf8(error_string.c_str()));
|
||||
setField("errorMessage", tr("Certificate Load Failed") + ": \n\n" + getErrorString(cert_load_error_code)) ;
|
||||
setStartId(Page_ErrorMessage);
|
||||
}
|
||||
}
|
||||
@ -372,9 +390,9 @@ bool ConnectFriendWizard::validateCurrentPage()
|
||||
case Page_Text:
|
||||
{
|
||||
std::string certstr = ui->friendCertEdit->toPlainText().toUtf8().constData();
|
||||
std::string error_string;
|
||||
uint32_t cert_load_error_code;
|
||||
|
||||
if (rsPeers->loadDetailsFromStringCert(certstr, peerDetails, error_string)) {
|
||||
if (rsPeers->loadDetailsFromStringCert(certstr, peerDetails, cert_load_error_code)) {
|
||||
mCertificate = certstr;
|
||||
#ifdef FRIEND_WIZARD_DEBUG
|
||||
std::cerr << "ConnectFriendWizard got id : " << peerDetails.id << "; gpg_id : " << peerDetails.gpg_id << std::endl;
|
||||
@ -382,7 +400,7 @@ bool ConnectFriendWizard::validateCurrentPage()
|
||||
break;
|
||||
}
|
||||
// error message
|
||||
setField("errorMessage", tr("Certificate Load Failed") + ": " + QString::fromUtf8(error_string.c_str()));
|
||||
setField("errorMessage", tr("Certificate Load Failed") + ": \n\n" + getErrorString(cert_load_error_code)) ;
|
||||
error = false;
|
||||
break;
|
||||
}
|
||||
@ -406,14 +424,14 @@ bool ConnectFriendWizard::validateCurrentPage()
|
||||
break;
|
||||
}
|
||||
|
||||
std::string error_string;
|
||||
if (rsPeers->loadDetailsFromStringCert(certstr, peerDetails, error_string)) {
|
||||
uint32_t cert_error_code;
|
||||
if (rsPeers->loadDetailsFromStringCert(certstr, peerDetails, cert_error_code)) {
|
||||
mCertificate = certstr;
|
||||
#ifdef FRIEND_WIZARD_DEBUG
|
||||
std::cerr << "ConnectFriendWizard got id : " << peerDetails.id << "; gpg_id : " << peerDetails.gpg_id << std::endl;
|
||||
#endif
|
||||
} else {
|
||||
setField("errorMessage", QString(tr("Certificate Load Failed:something is wrong with %1 ")).arg(fn) + ": " + QString::fromUtf8(error_string.c_str()));
|
||||
setField("errorMessage", QString(tr("Certificate Load Failed:something is wrong with %1 ")).arg(fn) + ": " + getErrorString(cert_error_code));
|
||||
error = false;
|
||||
}
|
||||
} else {
|
||||
|
@ -68,6 +68,9 @@ private slots:
|
||||
void groupCurrentIndexChanged(int index);
|
||||
|
||||
private:
|
||||
// returns the translated error string for the error code (to be found in rspeers.h)
|
||||
QString getErrorString(uint32_t) ;
|
||||
|
||||
bool error;
|
||||
RsPeerDetails peerDetails;
|
||||
std::string mCertificate;
|
||||
|
Loading…
x
Reference in New Issue
Block a user