- 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:
csoler 2012-12-22 21:22:03 +00:00
parent 0f26b85a88
commit d893d30883
8 changed files with 114 additions and 31 deletions

View File

@ -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

View File

@ -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

View File

@ -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) ;

View File

@ -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;

View File

@ -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 ;
}

View File

@ -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);

View File

@ -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 {

View File

@ -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;