- added new certificate format in ConfCertDialog and ConnectFriendWizard, with a button to switch to old format if necessary

- added automatic cleaning of certificates in both formats
- grouped all certificate cleaning/parsing code in rscertificate.cc
- removed unused files cleanupxpgp.h/cc
- added upper/lower case to rsid template.

The new format is to be tested. It is supposed to be much more robust than the previous format,
in particular, allowing any string for location names.


git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5410 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2012-08-13 19:37:50 +00:00
parent 64e171948c
commit 60f51c358c
21 changed files with 1037 additions and 1099 deletions

View File

@ -377,7 +377,6 @@ HEADERS += pqi/authssl.h \
pgp/pgphandler.h \
pgp/pgpkeyutil.h \
pgp/rscertificate.h \
pqi/cleanupxpgp.h \
pqi/p3cfgmgr.h \
pqi/p3peermgr.h \
pqi/p3linkmgr.h \
@ -517,7 +516,6 @@ SOURCES += pqi/authgpg.cc \
pgp/pgphandler.cc \
pgp/pgpkeyutil.cc \
pgp/rscertificate.cc \
pqi/cleanupxpgp.cc \
pqi/p3cfgmgr.cc \
pqi/p3peermgr.cc \
pqi/p3linkmgr.cc \

View File

@ -442,13 +442,12 @@ bool PGPHandler::GeneratePGPCertificate(const std::string& name, const std::stri
return true ;
}
std::string PGPHandler::makeRadixEncodedPGPKey(const ops_keydata_t *key)
std::string PGPHandler::makeRadixEncodedPGPKey(const ops_keydata_t *key,bool include_signatures)
{
ops_boolean_t armoured=ops_true;
ops_create_info_t* cinfo;
ops_memory_t *buf = NULL ;
ops_setup_memory_write(&cinfo, &buf, 0);
ops_boolean_t armoured = ops_true ;
if(key->type == OPS_PTAG_CT_PUBLIC_KEY)
{
@ -468,11 +467,17 @@ std::string PGPHandler::makeRadixEncodedPGPKey(const ops_keydata_t *key)
ops_writer_close(cinfo) ;
std::string akey((char *)ops_memory_get_data(buf),ops_memory_get_length(buf)) ;
std::string res((char *)ops_memory_get_data(buf),ops_memory_get_length(buf)) ;
ops_teardown_memory_write(cinfo,buf);
return akey ;
if(!include_signatures)
{
std::string tmp ;
if(PGPKeyManagement::createMinimalKey(res,tmp) )
res = tmp ;
}
return res ;
}
const ops_keydata_t *PGPHandler::getSecretKey(const PGPIdType& id) const
@ -494,7 +499,7 @@ const ops_keydata_t *PGPHandler::getPublicKey(const PGPIdType& id) const
return ops_keyring_get_key_by_index(_pubring,res->second._key_index) ;
}
std::string PGPHandler::SaveCertificateToString(const PGPIdType& id,bool)
std::string PGPHandler::SaveCertificateToString(const PGPIdType& id,bool include_signatures) const
{
RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures.
const ops_keydata_t *key = getPublicKey(id) ;
@ -505,7 +510,47 @@ std::string PGPHandler::SaveCertificateToString(const PGPIdType& id,bool)
return "" ;
}
return makeRadixEncodedPGPKey(key) ;
return makeRadixEncodedPGPKey(key,include_signatures) ;
}
bool PGPHandler::exportPublicKey(const PGPIdType& id,unsigned char *& mem_block,size_t& mem_size,bool armoured,bool include_signatures) const
{
RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures.
const ops_keydata_t *key = getPublicKey(id) ;
mem_block = NULL ;
if(key == NULL)
{
std::cerr << "Cannot output key " << id.toStdString() << ": not found in keyring." << std::endl;
return false ;
}
ops_create_info_t* cinfo;
ops_memory_t *buf = NULL ;
ops_setup_memory_write(&cinfo, &buf, 0);
if(ops_write_transferable_public_key_from_packet_data(key,armoured,cinfo) != ops_true)
{
std::cerr << "ERROR: This key cannot be processed by RetroShare because\nDSA certificates are not yet handled." << std::endl;
return false ;
}
ops_writer_close(cinfo) ;
mem_block = new unsigned char[ops_memory_get_length(buf)] ;
mem_size = ops_memory_get_length(buf) ;
memcpy(mem_block,ops_memory_get_data(buf),mem_size) ;
ops_teardown_memory_write(cinfo,buf);
if(!include_signatures)
{
size_t new_size ;
PGPKeyManagement::findLengthOfMinimalKey(mem_block,mem_size,new_size) ;
mem_size = new_size ;
}
return true ;
}
bool PGPHandler::exportGPGKeyPair(const std::string& filename,const PGPIdType& exported_key_id) const
@ -534,13 +579,68 @@ bool PGPHandler::exportGPGKeyPair(const std::string& filename,const PGPIdType& e
return false ;
}
fprintf(f,"%s\n", makeRadixEncodedPGPKey(pubkey).c_str()) ;
fprintf(f,"%s\n", makeRadixEncodedPGPKey(seckey).c_str()) ;
fprintf(f,"%s\n", makeRadixEncodedPGPKey(pubkey,true).c_str()) ;
fprintf(f,"%s\n", makeRadixEncodedPGPKey(seckey,true).c_str()) ;
fclose(f) ;
return true ;
}
bool PGPHandler::getGPGDetailsFromBinaryBlock(const unsigned char *mem_block,size_t mem_size,std::string& key_id, std::string& name, std::list<std::string>& signers) const
{
ops_keyring_t *tmp_keyring = allocateOPSKeyring();
ops_memory_t *mem = ops_memory_new() ;
ops_memory_add(mem,mem_block,mem_size);
if(!ops_keyring_read_from_mem(tmp_keyring,ops_false,mem))
{
ops_keyring_free(tmp_keyring) ;
free(tmp_keyring) ;
ops_memory_release(mem) ;
free(mem) ;
std::cerr << "Could not read key. Format error?" << std::endl;
//error_string = std::string("Could not read key. Format error?") ;
return false ;
}
ops_memory_release(mem) ;
free(mem) ;
//error_string.clear() ;
key_id = PGPIdType(tmp_keyring->keys[0].key_id).toStdString() ;
name = std::string((char *)tmp_keyring->keys[0].uids[0].user_id) ;
// now parse signatures.
//
ops_validate_result_t* result=(ops_validate_result_t*)ops_mallocz(sizeof *result);
ops_boolean_t res ;
{
RsStackMutex mtx(pgphandlerMtx) ; // lock access to PGP memory structures.
res = ops_validate_key_signatures(result,&tmp_keyring->keys[0],_pubring,cb_get_passphrase) ;
}
if(res == ops_false)
std::cerr << "(EE) Error in PGPHandler::validateAndUpdateSignatures(). Validation failed for at least some signatures." << std::endl;
// Parse signers.
//
if(result != NULL)
for(size_t i=0;i<result->valid_count;++i)
{
std::string signer_str = PGPIdType(result->valid_sigs[i].signer_id).toStdString() ;
signers.push_back(signer_str) ;
}
ops_validate_result_free(result) ;
ops_keyring_free(tmp_keyring) ;
free(tmp_keyring) ;
return true ;
}
bool PGPHandler::importGPGKeyPair(const std::string& filename,PGPIdType& imported_key_id,std::string& import_error)
{
import_error = "" ;

View File

@ -84,7 +84,9 @@ class PGPHandler
bool GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, PGPIdType& pgpId, std::string& errString) ;
bool LoadCertificateFromString(const std::string& pem, PGPIdType& gpg_id, std::string& error_string);
std::string SaveCertificateToString(const PGPIdType& id,bool include_signatures) ;
std::string SaveCertificateToString(const PGPIdType& id,bool include_signatures) const ;
bool exportPublicKey(const PGPIdType& id,unsigned char *& mem,size_t& mem_size,bool armoured,bool include_signatures) const ;
bool SignDataBin(const PGPIdType& id,const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen) ;
bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& withfingerprint) ;
@ -115,6 +117,10 @@ class PGPHandler
static void setPassphraseCallback(PassphraseCallback cb) ;
static PassphraseCallback passphraseCallback() { return _passphrase_callback ; }
// Gets info about the key. Who are the signers, what's the owner's name, etc.
//
bool getGPGDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,std::string& key_id, std::string& name, std::list<std::string>& signers) const ;
// Debug stuff.
virtual bool printKeys() const ;
@ -170,7 +176,7 @@ class PGPHandler
// Helper functions.
//
static std::string makeRadixEncodedPGPKey(const ops_keydata_t *key) ;
static std::string makeRadixEncodedPGPKey(const ops_keydata_t *key,bool include_signatures) ;
static ops_keyring_t *allocateOPSKeyring() ;
static void addNewKeyToOPSKeyring(ops_keyring_t*, const ops_keydata_t&) ;
static PassphraseCallback _passphrase_callback ;

View File

@ -35,6 +35,22 @@ bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::
Radix64::decode(radix_cert,keydata,len) ;
size_t new_len ;
findLengthOfMinimalKey((unsigned char *)keydata,len,new_len) ;
cleaned_certificate = makeArmouredKey((unsigned char*)keydata,new_len,version_string) ;
return true ;
}
catch(std::exception& e)
{
cleaned_certificate = "" ;
std::cerr << "Certificate cleaning failed: " << e.what() << std::endl;
return false ;
}
}
void PGPKeyManagement::findLengthOfMinimalKey(const unsigned char *keydata,size_t len,size_t& new_len)
{
unsigned char *data = (unsigned char *)keydata ;
#ifdef DEBUG_PGPUTIL
@ -75,15 +91,7 @@ bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::
break ;
}
cleaned_certificate = makeArmouredKey((unsigned char*)keydata,(uint64_t)data - (uint64_t)keydata,version_string) ;
return true ;
}
catch(std::exception& e)
{
cleaned_certificate = "" ;
std::cerr << "Certificate cleaning failed: " << e.what() << std::endl;
return false ;
}
new_len = (uint64_t)data - (uint64_t)keydata ;
}
std::string PGPKeyParser::extractRadixPartFromArmouredKey(const std::string& pgp_certificate,std::string& version_string)

View File

@ -59,6 +59,7 @@ class PGPKeyManagement
//
static bool createMinimalKey(const std::string& pgp_certificate,std::string& cleaned_certificate) ;
static void findLengthOfMinimalKey(const unsigned char *keydata,size_t key_len,size_t& minimal_key_len) ;
static std::string makeArmouredKey(const unsigned char *keydata,size_t key_size,const std::string& version_string) ;
private:
// Computes the 24 bits CRC checksum necessary to all PGP data.

View File

@ -3,6 +3,7 @@
#include <stdio.h>
#include <string.h>
#include <retroshare/rspeers.h>
#include <util/radix64.h>
#include <pgp/pgpkeyutil.h>
#include "rscertificate.h"
@ -21,36 +22,9 @@ 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 ;
std::string RsCertificate::toStdString_oldFormat() const
static bool is_acceptable_radix64Char(char c)
{
std::string res ;
res += PGPKeyManagement::makeArmouredKey(binary_pgp_key,binary_pgp_key_size,pgp_version) ;
res += SSLID_BEGIN_SECTION ;
res += location_id.toStdString() ;
res += ";" ;
res += LOCATION_BEGIN_SECTION ;
res += location_name ;
res += ";\n" ;
std::ostringstream os ;
os << LOCAL_IP_BEGIN_SECTION ;
os << (int)ipv4_internal_ip_and_port[0] << "." << (int)ipv4_internal_ip_and_port[1] << "." << (int)ipv4_internal_ip_and_port[2] << "." << (int)ipv4_internal_ip_and_port[3] ;
os << ":" ;
os << ipv4_internal_ip_and_port[4]*256+ipv4_internal_ip_and_port[5] ;
os << ";" ;
os << EXTERNAL_IP_BEGIN_SECTION ;
os << (int)ipv4_external_ip_and_port[0] << "." << (int)ipv4_external_ip_and_port[1] << "." << (int)ipv4_external_ip_and_port[2] << "." << (int)ipv4_external_ip_and_port[3] ;
os << ":" ;
os << ipv4_external_ip_and_port[4]*256+ipv4_external_ip_and_port[5] ;
os << ";" ;
res += os.str() ;
res += "\n" ;
return res ;
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '/' || '=' ;
}
RsCertificate::~RsCertificate()
@ -105,8 +79,21 @@ std::string RsCertificate::toStdString() const
Radix64::encode((char *)buf, p, out_string) ;
// Now slice up to 64 chars.
//
std::string out2 ;
static const int LINE_LENGTH = 64 ;
for(int i=0;i<(int)out_string.length();++i)
{
out2 += out_string[i] ;
if(i % LINE_LENGTH == LINE_LENGTH-1)
out2 += '\n' ;
}
delete[] buf ;
return out_string ;
return out2 ;
}
RsCertificate::RsCertificate(const std::string& str)
@ -121,6 +108,44 @@ RsCertificate::RsCertificate(const std::string& str)
throw std::runtime_error(err_string) ;
}
RsCertificate::RsCertificate(const RsPeerDetails& Detail, const unsigned char *binary_pgp_block,size_t binary_pgp_block_size)
:pgp_version("Version: OpenPGP:SDK v0.9")
{
if(binary_pgp_block_size == 0 || binary_pgp_block == NULL)
throw std::runtime_error("Cannot init a certificate with a void key block.") ;
if(Detail.isOnlyGPGdetail)
throw std::runtime_error("Cannot init a certificate with a RsPeerDetails with only GPG details.") ;
binary_pgp_key = new unsigned char[binary_pgp_block_size] ;
memcpy(binary_pgp_key,binary_pgp_block,binary_pgp_block_size) ;
binary_pgp_key_size = binary_pgp_block_size ;
location_id = SSLIdType( Detail.id ) ;
location_name = Detail.location ;
scan_ip(Detail.localAddr,Detail.localPort,ipv4_internal_ip_and_port) ;
scan_ip(Detail.extAddr,Detail.extPort,ipv4_external_ip_and_port) ;
dns_name = Detail.dyndns ;
}
void RsCertificate::scan_ip(const std::string& ip_string, unsigned short port,unsigned char *ip_and_port)
{
int d0,d1,d2,d3 ;
if(4 != sscanf(ip_string.c_str(),"%d.%d.%d.%d",&d0,&d1,&d2,&d3))
throw std::runtime_error( "Cannot parse ip from given string." );
ip_and_port[0] = d0 ;
ip_and_port[1] = d1 ;
ip_and_port[2] = d2 ;
ip_and_port[3] = d3 ;
ip_and_port[4] = (port >> 8 ) & 0xff ;
ip_and_port[5] = port & 0xff ;
}
bool RsCertificate::initFromString(const std::string& instr,std::string& err_string)
{
std::string str ;
@ -132,7 +157,7 @@ bool RsCertificate::initFromString(const std::string& instr,std::string& err_str
if(instr[i] == ' ' || instr[i] == '\t' || instr[i] == '\n')
continue ;
if(! ( (instr[i] >= '0' && instr[i] <= '9') || (instr[i] >= 'a' && instr[i] <= 'z') || (instr[i] >= 'A' && instr[i] <= 'Z') || (instr[i] == '+' || instr[i] == '/') || instr[i] == '='))
if(! is_acceptable_radix64Char(instr[i]))
return false ;
str += instr[i] ;
@ -158,7 +183,13 @@ bool RsCertificate::initFromString(const std::string& instr,std::string& err_str
total_s += 1 + ((unsigned long)buf-(unsigned long)buf2) ;
std::cerr << "Packet parse: read ptag " << (int)ptag << ", size " << size << ", total_s = " << total_s << std::endl;
if(total_s > size)
{
err_string = "Abnormal size read. Bigger than memory block." ;
return false ;
}
std::cerr << "Packet parse: read ptag " << (int)ptag << ", size " << s << ", total_s = " << total_s << ", expected total = " << size << std::endl;
switch(ptag)
{
@ -219,6 +250,488 @@ bool RsCertificate::initFromString(const std::string& instr,std::string& err_str
return true ;
}
std::string RsCertificate::ext_ip_string() const
{
std::ostringstream os ;
os << (int)ipv4_external_ip_and_port[0] << "." << (int)ipv4_external_ip_and_port[1] << "." << (int)ipv4_external_ip_and_port[2] << "." << (int)ipv4_external_ip_and_port[3] ;
return os.str() ;
}
std::string RsCertificate::loc_ip_string() const
{
std::ostringstream os ;
os << (int)ipv4_internal_ip_and_port[0] << "." << (int)ipv4_internal_ip_and_port[1] << "." << (int)ipv4_internal_ip_and_port[2] << "." << (int)ipv4_internal_ip_and_port[3] ;
return os.str() ;
}
unsigned short RsCertificate::ext_port_us() const
{
return (int)ipv4_external_ip_and_port[4]*256 + (int)ipv4_external_ip_and_port[5] ;
}
unsigned short RsCertificate::loc_port_us() const
{
return (int)ipv4_internal_ip_and_port[4]*256 + (int)ipv4_internal_ip_and_port[5] ;
}
bool RsCertificate::cleanCertificate(const std::string& input,std::string& output,Format& format,int& error_code)
{
if(cleanCertificate_oldFormat(input,output,error_code))
{
format = RS_CERTIFICATE_OLD_FORMAT ;
return true ;
}
if(cleanCertificate(input,output,error_code))
{
format = RS_CERTIFICATE_RADIX ;
return true ;
}
return false ;
}
std::string RsCertificate::armouredPGPKey() const
{
return PGPKeyManagement::makeArmouredKey(binary_pgp_key,binary_pgp_key_size,pgp_version) ;
}
// Yeah, this is simple, and that is what's good about the radix format. Can't be broken ;-)
//
bool RsCertificate::cleanCertificate(const std::string& instr,std::string& str,int& error_code)
{
error_code = RS_PEER_CERT_CLEANING_CODE_NO_ERROR ;
// 0 - clean the string and check that it is pure radix64
//
for(uint32_t i=0;i<instr.length();++i)
{
if(instr[i] == ' ' || instr[i] == '\t' || instr[i] == '\n')
continue ;
if(! is_acceptable_radix64Char(instr[i]))
{
error_code = RS_PEER_CERT_CLEANING_CODE_WRONG_RADIX_CHAR ;
return false ;
}
str += instr[i] ;
}
// Now slice up to 64 chars.
//
std::string str2 ;
static const int LINE_LENGTH = 64 ;
for(int i=0;i<(int)str.length();++i)
{
str2 += str[i] ;
if(i % LINE_LENGTH == LINE_LENGTH-1)
str2 += '\n' ;
}
str = str2 ;
return true ;
}
// All the code below should be removed when in 0.6. Certificates will only use the new format.
//
bool RsCertificate::cleanCertificate_oldFormat(const std::string& certstr,std::string& cleanCertificate,int& error_code)
{
error_code = RS_PEER_CERT_CLEANING_CODE_UNKOWN_ERROR ; // default
const std::string& badCertificate(certstr) ;
std::string pgpend("-----END PGP PUBLIC KEY BLOCK-----");
size_t pos = certstr.find(pgpend);
std::string peer_info ;
std::string cert ;
if (pos != std::string::npos)
{
pos += pgpend.length();
cert = certstr.substr(0, pos);
if (pos + 1 < certstr.length())
peer_info = certstr.substr(pos + 1);
}
else
{
error_code = RS_PEER_CERT_CLEANING_CODE_NO_END_TAG ;
return false ;
}
if(cert.empty())
return false ;
/*
Buffer for storing the cleaned certificate. In certain cases the
cleanCertificate can be larger than the badCertificate
*/
cleanCertificate = "";
//The entire certificate begin tag
const char * beginCertTag="-----BEGIN";
//The entire certificate end tag
const char * endCertTag="-----END";
//Tag containing dots. The common part of both start and end tags
const char * commonTag="-----";
//Only BEGIN part of the begin tag
const char * beginTag="BEGIN";
//Only END part of the end tag
const char * endTag="END";
//The start index of the ----- part of the certificate begin tag
size_t beginCertStartIdx1=0;
//The start index of the BEGIN part of the certificate begin tag
size_t beginCertStartIdx2=0;
//The start index of the end part(-----) of the certificate begin tag. The begin tag ends with -----. Example -----BEGIN XPGP CERTIFICATE-----
size_t beginCertEndIdx=0;
//The start index of the ----- part of the certificate end tag
size_t endCertStartIdx1=0;
//The start index of the END part of the certificate end tag
size_t endCertStartIdx2=0;
//The start index of the end part(-----) of the certificate end tag. The begin tag ends with -----. Example -----BEGIN XPGP CERTIFICATE-----
size_t endCertEndIdx=0;
//The length of the bad certificate.
size_t lengthOfCert=certstr.length();
//The current index value in the bad certificate
size_t currBadCertIdx=0;
//Temporary index value
size_t tmpIdx=0;
//Boolean flag showing if the begin tag or the end tag has been found
bool found=false;
/*
Calculating the value of the beginCertStartIdx1 and beginCertStartIdx2. Here
we first locate the occurance of ----- and then the location of BEGIN. Next
we check if there are any non space or non new-line characters between their
occureance. If there are any other characters between the two(----- and
BEGIN), other than space and new line then it means that it is the
certificate begin tag. Here we take care of the fact that we may have
introduced some spaces and newlines in the begin tag by mistake. This takes
care of the spaces and newlines between ----- and BEGIN.
*/
while(found==false && (beginCertStartIdx1=certstr.find(commonTag,tmpIdx))!=std::string::npos)
{
beginCertStartIdx2=certstr.find(beginTag,beginCertStartIdx1+strlen(commonTag));
tmpIdx=beginCertStartIdx1+strlen(commonTag);
if(beginCertStartIdx2!=std::string::npos)
{
found=true;
for(size_t i=beginCertStartIdx1+strlen(commonTag);i<beginCertStartIdx2;i++)
{
if(certstr[i]!=' ' && certstr[i]!='\n' )
{
found=false;
break;
}
}
}
else
{
break;
}
}
/*
begin tag not found
*/
if(!found)
{
std::cerr<<"Certificate corrupted beyond repair: No <------BEGIN > tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_BEGIN_TAG ;
return false;
}
beginCertEndIdx=certstr.find(commonTag,beginCertStartIdx2);
if(beginCertEndIdx==std::string::npos)
{
std::cerr<<"Certificate corrupted beyond repair: No <------BEGIN > tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_BEGIN_TAG ;
return false;
}
tmpIdx=beginCertEndIdx+strlen(commonTag);
found=false;
/*
Calculating the value of the endCertStartIdx1 and endCertStartIdx2. Here we first locate the occurance of ----- and then
the location of END. Next we check if there are any non space or non new-line characters between their occureance. If there are any other
characters between the two(----- and END), other than space and new line then it means that it is the certificate end tag.
Here we take care of the fact that we may have introduced some spaces and newlines in the end tag by mistake. This
takes care of the spaces and newlines between ----- and END.
*/
while(found==false && (endCertStartIdx1=certstr.find(commonTag,tmpIdx))!=std::string::npos)
{
endCertStartIdx2=certstr.find(endTag,endCertStartIdx1+strlen(commonTag));
tmpIdx=endCertStartIdx1+strlen(commonTag);
if(endCertStartIdx2!=std::string::npos)
{
found=true;
for(size_t i=endCertStartIdx1+strlen(commonTag);i<endCertStartIdx2;i++)
{
if(certstr[i]!=' '&& certstr[i]!='\n')
{
found=false;
break;
}
}
}
else
{
break;
}
}
/*
end tag not found
*/
if(!found)
{
std::cerr<<"Certificate corrupted beyond repair: No <------END > tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_END_TAG ;
return false;
}
endCertEndIdx=certstr.find(commonTag,endCertStartIdx2);
if(endCertEndIdx==std::string::npos || endCertEndIdx>=lengthOfCert)
{
std::cerr<<"Certificate corrupted beyond repair: No <------END > tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_END_TAG ;
return false;
}
/*
Copying the begin tag(-----BEGIN) to the clean certificate
*/
cleanCertificate += beginCertTag;
currBadCertIdx=beginCertStartIdx2+strlen(beginTag);
/*
Copying the name of the tag e.g XPGP CERTIFICATE. At the same time remove any white spaces and new line
characters.
*/
while(currBadCertIdx<beginCertEndIdx)
{
if(badCertificate[currBadCertIdx]=='\n')
{
currBadCertIdx++;
}
else if(badCertificate[currBadCertIdx]==' ' && (badCertificate[currBadCertIdx-1]==' '|| badCertificate[currBadCertIdx-1]=='\n') )
{
currBadCertIdx++;
}
else
{
cleanCertificate += badCertificate[currBadCertIdx];
currBadCertIdx++;
}
}
/*
If the last character is a space we need to remove it.
*/
if(cleanCertificate.substr(cleanCertificate.length()-1, 1) == " ")
{
cleanCertificate.erase(cleanCertificate.length()-1);
}
/*
Copying the end part of the certificate start tag(-----).
*/
cleanCertificate += commonTag;
cleanCertificate += "\n";
currBadCertIdx=currBadCertIdx+strlen(commonTag);
/*
Remove the white spaces between the end of the certificate begin tag and the actual
start of the certificate.
*/
while(badCertificate[currBadCertIdx]=='\n'|| badCertificate[currBadCertIdx]==' ')
{
currBadCertIdx++;
}
//keep the armor header
std::list<std::string> header;
header.push_back("Version");
header.push_back("Comment");
header.push_back("MessageID");
header.push_back("Hash");
header.push_back("Charset");
for (std::list<std::string>::iterator headerIt = header.begin (); headerIt != header.end(); headerIt++)
{
if (badCertificate.substr(currBadCertIdx, (*headerIt).length()) == *headerIt)
{
cleanCertificate += badCertificate.substr(currBadCertIdx, (*headerIt).length());
currBadCertIdx += (*headerIt).length();
while(currBadCertIdx<endCertStartIdx1 && badCertificate[currBadCertIdx]!='\n')
{
cleanCertificate += badCertificate[currBadCertIdx];
currBadCertIdx++;
}
cleanCertificate += "\n";
}
}
//add empty line after armor header
cleanCertificate += "\n";
//Start of the actual certificate. Remove spaces in the certificate
//and make sure there are 64 characters per line in the
//new cleaned certificate
int cntPerLine=0;
while(currBadCertIdx<endCertStartIdx1)
{
if(cntPerLine==64)
{
cleanCertificate += "\n";
cntPerLine=0;
}
if(badCertificate[currBadCertIdx]=='=') /* checksum */
break;
else if(badCertificate[currBadCertIdx]=='\t')
currBadCertIdx++;
else if(badCertificate[currBadCertIdx]==' ')
currBadCertIdx++;
else if(badCertificate[currBadCertIdx]=='\n')
currBadCertIdx++;
else if(is_acceptable_radix64Char(badCertificate[currBadCertIdx]))
{
cleanCertificate += badCertificate[currBadCertIdx];
cntPerLine++;
currBadCertIdx++;
}
else
{
std::cerr << "Warning: Invalid character in radix certificate encoding: " << badCertificate[currBadCertIdx] << std::endl;
currBadCertIdx++;
}
}
if(currBadCertIdx>=endCertStartIdx1)
{
std::cerr<<"Certificate corrupted beyond repair: No checksum, or no newline after first tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_CHECKSUM ;
return false;
}
while(currBadCertIdx < endCertStartIdx1 && (badCertificate[currBadCertIdx] == '=' || badCertificate[currBadCertIdx] == ' ' || badCertificate[currBadCertIdx] == '\n' ))
currBadCertIdx++ ;
switch(cntPerLine % 4)
{
case 0: break ;
case 1: std::cerr<<"Certificate corrupted beyond repair: wrongnumber of chars on last line (n%4=1)"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_WRONG_NUMBER;
return false ;
case 2: cleanCertificate += "==" ;
break ;
case 3: cleanCertificate += "=" ;
break ;
}
cleanCertificate += "\n=";
// if (badCertificate[currBadCertIdx] == '=')
// {
/* checksum */
while(currBadCertIdx<endCertStartIdx1)
{
if (badCertificate[currBadCertIdx]==' ')
{
currBadCertIdx++;
continue;
}
else if(badCertificate[currBadCertIdx]=='\n')
{
currBadCertIdx++;
continue;
}
cleanCertificate += badCertificate[currBadCertIdx];
cntPerLine++;
currBadCertIdx++;
}
// }
if(cleanCertificate.substr(cleanCertificate.length()-1,1)!="\n")
{
cleanCertificate += "\n";
// std::cerr<<"zeeeee"<<std::endl;
}
else
{
// std::cerr<<"zooooo"<<std::endl;
}
/*
Copying the begining part of the certificate end tag. Copying
-----END part of the tag.
*/
cleanCertificate += endCertTag;
currBadCertIdx=endCertStartIdx2+strlen(endTag);
/*
Copying the name of the certificate e.g XPGP CERTIFICATE. The end tag also has the
the name of the tag.
*/
while(currBadCertIdx<endCertEndIdx)
{
if(badCertificate[currBadCertIdx]=='\n')
{
currBadCertIdx++;
}
else if( badCertificate[currBadCertIdx]==' ' && (badCertificate[currBadCertIdx-1]==' '|| badCertificate[currBadCertIdx-1]=='\n'))
{
currBadCertIdx++;
}
else
{
cleanCertificate += badCertificate[currBadCertIdx];
currBadCertIdx++;
}
}
/*
If the last character is a space we need to remove it.
*/
if(cleanCertificate.substr(cleanCertificate.length()-1,1)==" ")
{
cleanCertificate.erase(cleanCertificate.length()-1);
}
/*
Copying the end part(-----) of the end tag in the certificate.
*/
cleanCertificate += commonTag;
cleanCertificate += "\n";
error_code = RS_PEER_CERT_CLEANING_CODE_NO_ERROR ;
cleanCertificate += peer_info ;
return true;
}
std::string RsCertificate::toStdString_oldFormat() const
{
std::string res ;
res += PGPKeyManagement::makeArmouredKey(binary_pgp_key,binary_pgp_key_size,pgp_version) ;
res += SSLID_BEGIN_SECTION ;
res += location_id.toStdString() ;
res += ";" ;
res += LOCATION_BEGIN_SECTION ;
res += location_name ;
res += ";\n" ;
std::ostringstream os ;
os << LOCAL_IP_BEGIN_SECTION ;
os << (int)ipv4_internal_ip_and_port[0] << "." << (int)ipv4_internal_ip_and_port[1] << "." << (int)ipv4_internal_ip_and_port[2] << "." << (int)ipv4_internal_ip_and_port[3] ;
os << ":" ;
os << ipv4_internal_ip_and_port[4]*256+ipv4_internal_ip_and_port[5] ;
os << ";" ;
os << EXTERNAL_IP_BEGIN_SECTION ;
os << (int)ipv4_external_ip_and_port[0] << "." << (int)ipv4_external_ip_and_port[1] << "." << (int)ipv4_external_ip_and_port[2] << "." << (int)ipv4_external_ip_and_port[3] ;
os << ":" ;
os << ipv4_external_ip_and_port[4]*256+ipv4_external_ip_and_port[5] ;
os << ";" ;
res += os.str() ;
res += "\n" ;
return res ;
}
bool RsCertificate::initFromString_oldFormat(const std::string& certstr,std::string& err_string)
{
//parse the text to get ip address
@ -314,20 +827,7 @@ bool RsCertificate::initFromString_oldFormat(const std::string& certstr,std::str
sscanf(local_port.c_str(), "%hu", &localPort);
}
int d0,d1,d2,d3 ;
if(4 != sscanf(local_ip.c_str(),"%d.%d.%d.%d",&d0,&d1,&d2,&d3))
{
err_string = "Cannot parse ip from given string." ;
return false ;
}
ipv4_internal_ip_and_port[0] = d0 ;
ipv4_internal_ip_and_port[1] = d1 ;
ipv4_internal_ip_and_port[2] = d2 ;
ipv4_internal_ip_and_port[3] = d3 ;
ipv4_internal_ip_and_port[4] = (localPort >> 8 ) & 0xff ;
ipv4_internal_ip_and_port[5] = localPort & 0xff ;
scan_ip(local_ip,localPort,ipv4_internal_ip_and_port) ;
}
}
@ -352,20 +852,7 @@ bool RsCertificate::initFromString_oldFormat(const std::string& certstr,std::str
sscanf(ext_port.c_str(), "%hu", &extPort);
}
int d0,d1,d2,d3 ;
if(4 != sscanf(ext_ip.c_str(),"%d.%d.%d.%d",&d0,&d1,&d2,&d3))
{
err_string = "Cannot parse ip from given string." ;
return false ;
}
ipv4_external_ip_and_port[0] = d0 ;
ipv4_external_ip_and_port[1] = d1 ;
ipv4_external_ip_and_port[2] = d2 ;
ipv4_external_ip_and_port[3] = d3 ;
ipv4_external_ip_and_port[4] = (extPort >> 8 ) & 0xff ;
ipv4_external_ip_and_port[5] = extPort & 0xff ;
scan_ip(ext_ip,extPort,ipv4_external_ip_and_port) ;
}
}
@ -397,4 +884,3 @@ bool RsCertificate::initFromString_oldFormat(const std::string& certstr,std::str

View File

@ -3,6 +3,8 @@
#include <string>
#include <util/rsid.h>
class RsPeerDetails ;
static const int SSL_ID_SIZE = 16 ;
typedef t_RsGenericIdType<SSL_ID_SIZE> SSLIdType ;
@ -10,16 +12,45 @@ typedef t_RsGenericIdType<SSL_ID_SIZE> SSLIdType ;
class RsCertificate
{
public:
// Constructs from text
typedef enum { RS_CERTIFICATE_OLD_FORMAT, RS_CERTIFICATE_RADIX } Format ;
// Constructs from text.
// - old format: The input string must comply with the GPG format (See RFC4880)
// - new format: The input string should only contain radix chars and spaces/LF/tabs.
//
RsCertificate(const std::string& input_string) ;
// Constructs from binary gpg key, and RsPeerDetails.
//
RsCertificate(const RsPeerDetails& details,const unsigned char *gpg_mem_block,size_t gpg_mem_block_size) ;
// Constructs
virtual ~RsCertificate();
// Outut to text
std::string toStdString_oldFormat() const ;
std::string toStdString() const ;
std::string ext_ip_string() const ;
std::string loc_ip_string() const ;
std::string dns_string() const { return dns_name ; }
std::string sslid_string() const { return location_id.toStdString(false) ; }
std::string armouredPGPKey() const ;
unsigned short ext_port_us() const ;
unsigned short loc_port_us() const ;
const unsigned char *pgp_key() const { return binary_pgp_key ; }
const 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) ;
private:
static bool cleanCertificate(const std::string& input,std::string& output,int&) ; // new radix format
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) ;

View File

@ -41,7 +41,6 @@
#include <sstream>
#include <algorithm>
#include "serialiser/rsconfigitems.h"
#include "cleanupxpgp.h"
#define LIMIT_CERTIFICATE_SIZE 1
#define MAX_CERTIFICATE_SIZE 10000
@ -492,14 +491,18 @@ bool AuthGPG::getGPGSignedList(std::list<std::string> &ids)
bool AuthGPG::getCachedGPGCertificate(const std::string &id, std::string &certificate)
{
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
certificate = PGPHandler::SaveCertificateToString(PGPIdType(id),false) ;
#ifdef LIMIT_CERTIFICATE_SIZE
std::string cleaned_key ;
if(PGPKeyManagement::createMinimalKey(certificate,cleaned_key))
certificate = cleaned_key ;
certificate = PGPHandler::SaveCertificateToString(PGPIdType(id),false) ;
#else
certificate = PGPHandler::SaveCertificateToString(PGPIdType(id),true) ;
#endif
// #ifdef LIMIT_CERTIFICATE_SIZE
// std::string cleaned_key ;
// if(PGPKeyManagement::createMinimalKey(certificate,cleaned_key))
// certificate = cleaned_key ;
// #endif
return certificate.length() > 0 ;
}
@ -525,13 +528,14 @@ std::string AuthGPG::SaveCertificateToString(const std::string &id,bool include_
std::string tmp = PGPHandler::SaveCertificateToString(PGPIdType(id),include_signatures) ;
// Try to remove signatures manually.
//
std::string cleaned_key ;
// // Try to remove signatures manually.
// //
// std::string cleaned_key ;
//
// if( (!include_signatures) && PGPKeyManagement::createMinimalKey(tmp,cleaned_key))
// return cleaned_key ;
// else
if( (!include_signatures) && PGPKeyManagement::createMinimalKey(tmp,cleaned_key))
return cleaned_key ;
else
return tmp;
}

View File

@ -30,7 +30,6 @@
#include "authssl.h"
#include "sslfns.h"
#include "cleanupxpgp.h"
#include "pqinetwork.h"
#include "authgpg.h"

View File

@ -1,418 +0,0 @@
/*
* libretroshare/src/pqi: cleanupxpgp.cc
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2008 by Sourashis Roy
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#include "cleanupxpgp.h"
#include <iostream>
#include <string.h> //strlen
#include <list>
#include <retroshare/rspeers.h>
/*
Method for cleaning up the certificate. This method removes any unnecessay white spaces and unnecessary
new line characters in the certificate. Also it makes sure that there are 64 characters per line in
the certificate. This function removes white spaces and new line characters in the entire segment
-----BEGIN XPGP CERTIFICATE-----
<CERTIFICATE>
-----END XPGP CERTIFICATE-----
We also take care of correcting cases like ----- BEGIN. Here extra empty spaces
have been introduced between ----- and BEGIN. Similarly for the
end tag we take care of cases like ----- END XPGP . Here extra empty spaces have been
introduced and the actual tag should have been -----END XPGP
*/
static bool is_acceptable_radix64Char(char c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '+' || c == '/' ;
}
std::string cleanUpCertificate(const std::string& badCertificate,int& error_code)
{
error_code = RS_PEER_CERT_CLEANING_CODE_UNKOWN_ERROR ; // default
/*
Buffer for storing the cleaned certificate. In certain cases the
cleanCertificate can be larger than the badCertificate
*/
std::string cleanCertificate;
//The entire certificate begin tag
const char * beginCertTag="-----BEGIN";
//The entire certificate end tag
const char * endCertTag="-----END";
//Tag containing dots. The common part of both start and end tags
const char * commonTag="-----";
//Only BEGIN part of the begin tag
const char * beginTag="BEGIN";
//Only END part of the end tag
const char * endTag="END";
//The start index of the ----- part of the certificate begin tag
size_t beginCertStartIdx1=0;
//The start index of the BEGIN part of the certificate begin tag
size_t beginCertStartIdx2=0;
//The start index of the end part(-----) of the certificate begin tag. The begin tag ends with -----. Example -----BEGIN XPGP CERTIFICATE-----
size_t beginCertEndIdx=0;
//The start index of the ----- part of the certificate end tag
size_t endCertStartIdx1=0;
//The start index of the END part of the certificate end tag
size_t endCertStartIdx2=0;
//The start index of the end part(-----) of the certificate end tag. The begin tag ends with -----. Example -----BEGIN XPGP CERTIFICATE-----
size_t endCertEndIdx=0;
//The length of the bad certificate.
size_t lengthOfCert=badCertificate.length();
//The current index value in the bad certificate
size_t currBadCertIdx=0;
//Temporary index value
size_t tmpIdx=0;
//Boolean flag showing if the begin tag or the end tag has been found
bool found=false;
/*
Calculating the value of the beginCertStartIdx1 and beginCertStartIdx2. Here
we first locate the occurance of ----- and then the location of BEGIN. Next
we check if there are any non space or non new-line characters between their
occureance. If there are any other characters between the two(----- and
BEGIN), other than space and new line then it means that it is the
certificate begin tag. Here we take care of the fact that we may have
introduced some spaces and newlines in the begin tag by mistake. This takes
care of the spaces and newlines between ----- and BEGIN.
*/
while(found==false && (beginCertStartIdx1=badCertificate.find(commonTag,tmpIdx))!=std::string::npos)
{
beginCertStartIdx2=badCertificate.find(beginTag,beginCertStartIdx1+strlen(commonTag));
tmpIdx=beginCertStartIdx1+strlen(commonTag);
if(beginCertStartIdx2!=std::string::npos)
{
found=true;
for(size_t i=beginCertStartIdx1+strlen(commonTag);i<beginCertStartIdx2;i++)
{
if(badCertificate[i]!=' ' && badCertificate[i]!='\n' )
{
found=false;
break;
}
}
}
else
{
break;
}
}
/*
begin tag not found
*/
if(!found)
{
std::cerr<<"Certificate corrupted beyond repair: No <------BEGIN > tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_BEGIN_TAG ;
return badCertificate;
}
beginCertEndIdx=badCertificate.find(commonTag,beginCertStartIdx2);
if(beginCertEndIdx==std::string::npos)
{
std::cerr<<"Certificate corrupted beyond repair: No <------BEGIN > tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_BEGIN_TAG ;
return badCertificate;
}
tmpIdx=beginCertEndIdx+strlen(commonTag);
found=false;
/*
Calculating the value of the endCertStartIdx1 and endCertStartIdx2. Here we first locate the occurance of ----- and then
the location of END. Next we check if there are any non space or non new-line characters between their occureance. If there are any other
characters between the two(----- and END), other than space and new line then it means that it is the certificate end tag.
Here we take care of the fact that we may have introduced some spaces and newlines in the end tag by mistake. This
takes care of the spaces and newlines between ----- and END.
*/
while(found==false && (endCertStartIdx1=badCertificate.find(commonTag,tmpIdx))!=std::string::npos)
{
endCertStartIdx2=badCertificate.find(endTag,endCertStartIdx1+strlen(commonTag));
tmpIdx=endCertStartIdx1+strlen(commonTag);
if(endCertStartIdx2!=std::string::npos)
{
found=true;
for(size_t i=endCertStartIdx1+strlen(commonTag);i<endCertStartIdx2;i++)
{
if(badCertificate[i]!=' '&& badCertificate[i]!='\n')
{
found=false;
break;
}
}
}
else
{
break;
}
}
/*
end tag not found
*/
if(!found)
{
std::cerr<<"Certificate corrupted beyond repair: No <------END > tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_END_TAG ;
return badCertificate;
}
endCertEndIdx=badCertificate.find(commonTag,endCertStartIdx2);
if(endCertEndIdx==std::string::npos || endCertEndIdx>=lengthOfCert)
{
std::cerr<<"Certificate corrupted beyond repair: No <------END > tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_END_TAG ;
return badCertificate;
}
/*
Copying the begin tag(-----BEGIN) to the clean certificate
*/
cleanCertificate += beginCertTag;
currBadCertIdx=beginCertStartIdx2+strlen(beginTag);
/*
Copying the name of the tag e.g XPGP CERTIFICATE. At the same time remove any white spaces and new line
characters.
*/
while(currBadCertIdx<beginCertEndIdx)
{
if(badCertificate[currBadCertIdx]=='\n')
{
currBadCertIdx++;
}
else if(badCertificate[currBadCertIdx]==' ' && (badCertificate[currBadCertIdx-1]==' '|| badCertificate[currBadCertIdx-1]=='\n') )
{
currBadCertIdx++;
}
else
{
cleanCertificate += badCertificate[currBadCertIdx];
currBadCertIdx++;
}
}
/*
If the last character is a space we need to remove it.
*/
if(cleanCertificate.substr(cleanCertificate.length()-1, 1) == " ")
{
cleanCertificate.erase(cleanCertificate.length()-1);
}
/*
Copying the end part of the certificate start tag(-----).
*/
cleanCertificate += commonTag;
cleanCertificate += "\n";
currBadCertIdx=currBadCertIdx+strlen(commonTag);
/*
Remove the white spaces between the end of the certificate begin tag and the actual
start of the certificate.
*/
while(badCertificate[currBadCertIdx]=='\n'|| badCertificate[currBadCertIdx]==' ')
{
currBadCertIdx++;
}
//keep the armor header
std::list<std::string> header;
header.push_back("Version");
header.push_back("Comment");
header.push_back("MessageID");
header.push_back("Hash");
header.push_back("Charset");
for (std::list<std::string>::iterator headerIt = header.begin (); headerIt != header.end(); headerIt++)
{
if (badCertificate.substr(currBadCertIdx, (*headerIt).length()) == *headerIt)
{
cleanCertificate += badCertificate.substr(currBadCertIdx, (*headerIt).length());
currBadCertIdx += (*headerIt).length();
while(currBadCertIdx<endCertStartIdx1 && badCertificate[currBadCertIdx]!='\n')
{
cleanCertificate += badCertificate[currBadCertIdx];
currBadCertIdx++;
}
cleanCertificate += "\n";
}
}
//add empty line after armor header
cleanCertificate += "\n";
//Start of the actual certificate. Remove spaces in the certificate
//and make sure there are 64 characters per line in the
//new cleaned certificate
int cntPerLine=0;
while(currBadCertIdx<endCertStartIdx1)
{
if(cntPerLine==64)
{
cleanCertificate += "\n";
cntPerLine=0;
}
if(badCertificate[currBadCertIdx]=='=') /* checksum */
break;
else if(badCertificate[currBadCertIdx]=='\t')
currBadCertIdx++;
else if(badCertificate[currBadCertIdx]==' ')
currBadCertIdx++;
else if(badCertificate[currBadCertIdx]=='\n')
currBadCertIdx++;
else if(is_acceptable_radix64Char(badCertificate[currBadCertIdx]))
{
cleanCertificate += badCertificate[currBadCertIdx];
cntPerLine++;
currBadCertIdx++;
}
else
{
std::cerr << "Warning: Invalid character in radix certificate encoding: " << badCertificate[currBadCertIdx] << std::endl;
currBadCertIdx++;
}
}
if(currBadCertIdx>=endCertStartIdx1)
{
std::cerr<<"Certificate corrupted beyond repair: No checksum, or no newline after first tag"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_NO_CHECKSUM ;
return badCertificate;
}
while(currBadCertIdx < endCertStartIdx1 && (badCertificate[currBadCertIdx] == '=' || badCertificate[currBadCertIdx] == ' ' || badCertificate[currBadCertIdx] == '\n' ))
currBadCertIdx++ ;
switch(cntPerLine % 4)
{
case 0: break ;
case 1: std::cerr<<"Certificate corrupted beyond repair: wrongnumber of chars on last line (n%4=1)"<<std::endl;
error_code = RS_PEER_CERT_CLEANING_CODE_WRONG_NUMBER;
return badCertificate ;
case 2: cleanCertificate += "==" ;
break ;
case 3: cleanCertificate += "=" ;
break ;
}
cleanCertificate += "\n=";
// if (badCertificate[currBadCertIdx] == '=')
// {
/* checksum */
while(currBadCertIdx<endCertStartIdx1)
{
if (badCertificate[currBadCertIdx]==' ')
{
currBadCertIdx++;
continue;
}
else if(badCertificate[currBadCertIdx]=='\n')
{
currBadCertIdx++;
continue;
}
cleanCertificate += badCertificate[currBadCertIdx];
cntPerLine++;
currBadCertIdx++;
}
// }
if(cleanCertificate.substr(cleanCertificate.length()-1,1)!="\n")
{
cleanCertificate += "\n";
// std::cerr<<"zeeeee"<<std::endl;
}
else
{
// std::cerr<<"zooooo"<<std::endl;
}
/*
Copying the begining part of the certificate end tag. Copying
-----END part of the tag.
*/
cleanCertificate += endCertTag;
currBadCertIdx=endCertStartIdx2+strlen(endTag);
/*
Copying the name of the certificate e.g XPGP CERTIFICATE. The end tag also has the
the name of the tag.
*/
while(currBadCertIdx<endCertEndIdx)
{
if(badCertificate[currBadCertIdx]=='\n')
{
currBadCertIdx++;
}
else if( badCertificate[currBadCertIdx]==' ' && (badCertificate[currBadCertIdx-1]==' '|| badCertificate[currBadCertIdx-1]=='\n'))
{
currBadCertIdx++;
}
else
{
cleanCertificate += badCertificate[currBadCertIdx];
currBadCertIdx++;
}
}
/*
If the last character is a space we need to remove it.
*/
if(cleanCertificate.substr(cleanCertificate.length()-1,1)==" ")
{
cleanCertificate.erase(cleanCertificate.length()-1);
}
/*
Copying the end part(-----) of the end tag in the certificate.
*/
cleanCertificate += commonTag;
cleanCertificate += "\n";
error_code = RS_PEER_CERT_CLEANING_CODE_NO_ERROR ;
return cleanCertificate;
}
#ifdef UNUSED_CODE
int findEndIdxOfCertStartTag(std::string badCertificate)
{
size_t idxTag1=0;
size_t tmpIdx=0;
size_t idxTag2=0;
const char * tag1="---";
const char * tag2="---";
bool found=false;
while(found==false && (idxTag1=badCertificate.find(tag1,tmpIdx))!=std::string::npos)
{
idxTag2=badCertificate.find(tag2,idxTag1+strlen(tag1));
if(idxTag2!=std::string::npos)
{
found=true;
for(size_t i=idxTag1+strlen(tag1);i<idxTag2;i++)
{
if(badCertificate[i]!=' ')
{
found=false;
break;
}
}
}
else
{
break;
}
}
return 1;
}
#endif

View File

@ -1,57 +0,0 @@
/*
* libretroshare/src/pqi: cleanupxpgp.h
*
* 3P/PQI network interface for RetroShare.
*
* Copyright 2008 by Sourashis Roy
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*
* Please report all bugs and problems to "retroshare@lunamutt.com".
*
*/
#ifndef PQI_XPGP_CLEANUP_H
#define PQI_XPGP_CLEANUP_H
#include <string>
//! Converts invitation to clean XPGP certificate
//! This function was used for extracting XPGP certificates from invitation
//!letters. Typical input was something like
//! You have been invited to join the retroshare community by: beardog-unstable-02
//!
//! Retroshare is a Friend-2-Friend network that enables you to communicate securely and privately ....
//! ... text stuff .....
//!
//!-----BEGIN XPGP CERTIFICATE-----
//!Version: ...
//!
//!MIICxQIBADCCAUkCAQAwHhcNMDkwMjI4MTgzODIyWhcNMTQwMjI3MTgzODIyWjCC
//! ...more ines here...
//!mEuhG8UmDIzC1jeTu8rTMnO+DO3FH/cek1vlfFl4t9g/xktG9U4SPLg=
//!=checksum
//!-----END XPGP CERTIFICATE-----
//!
//! In the newer gui version, users send each other almost clean certificates,
//! so this functon is used only to avoid possible bugs with line endings
// Error codes (need appropriate message andtranslation in GUI) are listed in rspeers.h
//
std::string cleanUpCertificate(const std::string& badCertificate,int& error_code);
#endif

View File

@ -79,6 +79,7 @@ const int RS_PEER_CERT_CLEANING_CODE_NO_BEGIN_TAG = 0x02 ;
const int RS_PEER_CERT_CLEANING_CODE_NO_END_TAG = 0x03 ;
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 ;
/* LinkType Flags */
@ -263,17 +264,21 @@ virtual bool getAllowServerIPDetermination() = 0 ;
virtual bool getAllowTunnelConnection() = 0 ;
/* Auth Stuff */
virtual std::string GetRetroshareInvite(const std::string& ssl_id,bool include_signatures) = 0;
virtual std::string GetRetroshareInvite(bool include_signatures) = 0;
virtual std::string GetRetroshareInvite(const std::string& ssl_id,bool include_signatures,bool old_format = false) = 0;
virtual std::string GetRetroshareInvite(bool include_signatures,bool old_format = false) = 0;
virtual bool hasExportMinimal() = 0 ;
// Add keys to the keyring
virtual bool loadCertificateFromFile(const std::string &fname, std::string &ssl_id, std::string &gpg_id) = 0;
virtual bool loadDetailsFromStringCert(const std::string &certGPG, RsPeerDetails &pd,std::string& error_string) = 0;
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 cleanCertificate(const std::string &certstr, std::string &cleanCert,int& error_code) = 0;
virtual bool saveCertificateToFile(const std::string &id, const std::string &fname) = 0;
virtual std::string saveCertificateToString(const std::string &id) = 0;
//virtual bool setAcceptToConnectGPGCertificate(const std::string &gpg_id, bool acceptance) = 0;
virtual bool signGPGCertificate(const std::string &gpg_id) = 0;
virtual bool trustGPGCertificate(const std::string &gpg_id, uint32_t trustlvl) = 0;

View File

@ -33,8 +33,8 @@
#include "pqi/authssl.h"
#include "pqi/authgpg.h"
#include "retroshare/rsinit.h"
#include "pqi/cleanupxpgp.h"
#include "pgp/rscertificate.h"
#include <iostream>
#include <fstream>
@ -405,193 +405,6 @@ bool p3Peers::getPeerDetails(const std::string &id, RsPeerDetails &d)
return true;
}
#if 0
bool p3Peers::getPeerDetails(const std::string &id, RsPeerDetails &d)
{
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::getPeerDetails() called for id : " << id << std::endl;
#endif
//first, check if it's a gpg or a ssl id.
std::string sOwnId = AuthSSL::getAuthSSL()->OwnId();
peerState ps;
if (id != sOwnId && !mPeerMgr->getFriendNetStatus(id, ps)) {
//assume is not SSL, because every ssl_id has got a friend correspondance in mConnMgr
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::getPeerDetails() got a gpg id and is returning GPG details only for id : " << id << std::endl;
#endif
d.isOnlyGPGdetail = true;
return this->getGPGDetails(id, d);
}
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::getPeerDetails() got a SSL id and is returning SSL and GPG details for id : " << id << std::endl;
#endif
if (id == sOwnId) {
mPeerMgr->getOwnNetStatus(ps);
ps.gpg_id = AuthGPG::getAuthGPG()->getGPGOwnId();
}
/* get from gpg (first), to fill in the sign and trust details */
/* don't retrun now, we've got fill in the ssl and connection info */
this->getGPGDetails(ps.gpg_id, d);
d.isOnlyGPGdetail = false;
//get the ssl details
d.id = id;
d.location = ps.location;
/* generate */
d.authcode = "AUTHCODE";
/* fill from pcs */
d.localAddr = rs_inet_ntoa(ps.localaddr.sin_addr);
d.localPort = ntohs(ps.localaddr.sin_port);
d.extAddr = rs_inet_ntoa(ps.serveraddr.sin_addr);
d.extPort = ntohs(ps.serveraddr.sin_port);
d.dyndns = ps.dyndns;
d.lastConnect = ps.lastcontact;
d.connectPeriod = 0;
std::list<pqiIpAddress>::iterator it;
for(it = ps.ipAddrs.mLocal.mAddrs.begin();
it != ps.ipAddrs.mLocal.mAddrs.end(); it++)
{
std::ostringstream toto; // please do not use std::ostringstream
toto << ntohs(it->mAddr.sin_port) << " " << (time(NULL) - it->mSeenTime) << " sec";
d.ipAddressList.push_back("L:" + std::string(rs_inet_ntoa(it->mAddr.sin_addr)) + ":" + toto.str());
}
for(it = ps.ipAddrs.mExt.mAddrs.begin();
it != ps.ipAddrs.mExt.mAddrs.end(); it++)
{
std::ostringstream toto; // please do not use std::ostringstream
toto << ntohs(it->mAddr.sin_port) << " " << (time(NULL) - it->mSeenTime) << " sec";
d.ipAddressList.push_back("E:" + std::string(rs_inet_ntoa(it->mAddr.sin_addr)) + ":" + toto.str());
}
switch(ps.netMode & RS_NET_MODE_ACTUAL)
{
case RS_NET_MODE_EXT:
d.netMode = RS_NETMODE_EXT;
break;
case RS_NET_MODE_UPNP:
d.netMode = RS_NETMODE_UPNP;
break;
case RS_NET_MODE_UDP:
d.netMode = RS_NETMODE_UDP;
break;
case RS_NET_MODE_UNREACHABLE:
case RS_NET_MODE_UNKNOWN:
default:
d.netMode = RS_NETMODE_UNREACHABLE;
break;
}
if (ps.netMode & RS_NET_MODE_TRY_EXT)
{
d.tryNetMode = RS_NETMODE_EXT;
}
else if (ps.netMode & RS_NET_MODE_TRY_UPNP)
{
d.tryNetMode = RS_NETMODE_UPNP;
}
else
{
d.tryNetMode = RS_NETMODE_UDP;
}
d.visState = 0;
if (!(ps.visState & RS_VIS_STATE_NODISC))
{
d.visState |= RS_VS_DISC_ON;
}
if (!(ps.visState & RS_VIS_STATE_NODHT))
{
d.visState |= RS_VS_DHT_ON;
}
/* Translate */
peerConnectState pcs;
if (!mLinkMgr->getFriendNetStatus(id, pcs))
{
std::cerr << "p3Peers::getPeerDetails() ERROR No Link Information : " << id << std::endl;
return true;
}
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::getPeerDetails() got a SSL id and is returning SSL and GPG details for id : " << id << std::endl;
#endif
d.state = 0;
if (pcs.state & RS_PEER_S_FRIEND)
d.state |= RS_PEER_STATE_FRIEND;
if (pcs.state & RS_PEER_S_ONLINE)
d.state |= RS_PEER_STATE_ONLINE;
if (pcs.state & RS_PEER_S_CONNECTED)
d.state |= RS_PEER_STATE_CONNECTED;
if (pcs.state & RS_PEER_S_UNREACHABLE)
d.state |= RS_PEER_STATE_UNREACHABLE;
/* Finally determine AutoConnect Status */
d.foundDHT = pcs.dht.found;
d.connectState = 0;
d.connectStateString.clear();
if (pcs.inConnAttempt)
{
if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_TUNNEL) {
d.connectState = RS_PEER_CONNECTSTATE_TRYING_TUNNEL;
} else if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_TCP_ALL) {
d.connectState = RS_PEER_CONNECTSTATE_TRYING_TCP;
std::ostringstream str; // please do not use std::ostringstream
str << rs_inet_ntoa(pcs.currentConnAddrAttempt.addr.sin_addr) << ":" << ntohs(pcs.currentConnAddrAttempt.addr.sin_port);
d.connectStateString = str.str();
} else if (pcs.currentConnAddrAttempt.type & RS_NET_CONN_UDP_ALL) {
d.connectState = RS_PEER_CONNECTSTATE_TRYING_UDP;
std::ostringstream str; // please do not use std::ostringstream
str << rs_inet_ntoa(pcs.currentConnAddrAttempt.addr.sin_addr) << ":" << ntohs(pcs.currentConnAddrAttempt.addr.sin_port);
d.connectStateString = str.str();
}
}
else if (pcs.state & RS_PEER_S_CONNECTED)
{
if (pcs.connecttype == RS_NET_CONN_TCP_ALL)
{
d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TCP;
}
else if (pcs.connecttype == RS_NET_CONN_UDP_ALL)
{
d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UDP;
}
else if (pcs.connecttype == RS_NET_CONN_TUNNEL)
{
d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_TUNNEL;
}
else
{
d.connectState = RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN;
}
}
return true;
}
#endif
bool p3Peers::isKeySupported(const std::string& id)
{
return AuthGPG::getAuthGPG()->isKeySupported(id);
@ -1001,17 +814,16 @@ p3Peers::setVisState(const std::string &id, uint32_t extVisState)
//===========================================================================
/* Auth Stuff */
std::string
p3Peers::GetRetroshareInvite(bool include_signatures)
p3Peers::GetRetroshareInvite(bool include_signatures,bool old_format)
{
return GetRetroshareInvite(getOwnId(),include_signatures);
return GetRetroshareInvite(getOwnId(),include_signatures,old_format);
}
std::string
p3Peers::GetRetroshareInvite(const std::string& ssl_id,bool include_signatures)
std::string p3Peers::GetRetroshareInvite(const std::string& ssl_id,bool include_signatures,bool old_format)
{
#ifdef P3PEERS_DEBUG
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::GetRetroshareInvite()" << std::endl;
#endif
#endif
//add the sslid, location, ip local and external address after the signature
RsPeerDetails Detail;
@ -1019,30 +831,39 @@ p3Peers::GetRetroshareInvite(const std::string& ssl_id,bool include_signatures)
if (getPeerDetails(ssl_id, Detail))
{
invite = AuthGPG::getAuthGPG()->SaveCertificateToString(Detail.gpg_id,include_signatures);
unsigned char *mem_block = NULL;
size_t mem_block_size = 0;
if(!Detail.isOnlyGPGdetail)
if(!AuthGPG::getAuthGPG()->exportPublicKey(PGPIdType(Detail.gpg_id),mem_block,mem_block_size,false,include_signatures))
{
invite += CERT_SSL_ID + Detail.id + ";";
invite += CERT_LOCATION + Detail.location + ";\n";
invite += CERT_LOCAL_IP + Detail.localAddr + ":";
rs_sprintf_append(invite, "%u;", Detail.localPort);
invite += CERT_EXT_IP + Detail.extAddr + ":";
rs_sprintf_append(invite, "%u;", Detail.extPort);
if (!Detail.dyndns.empty()) {
invite += "\n" + CERT_DYNDNS + Detail.dyndns + ";";
}
}
std::cerr << "Cannot output certificate for id \"" << Detail.gpg_id << "\". Sorry." << std::endl;
return "" ;
}
#ifdef P3PEERS_DEBUG
RsCertificate cert( Detail,mem_block,mem_block_size ) ;
if(old_format)
return cert.toStdString_oldFormat() ;
else
return cert.toStdString() ;
}
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::GetRetroshareInvite() returns : \n" << invite << std::endl;
#endif
#endif
return invite;
}
//===========================================================================
bool p3Peers::loadCertificateFromString(const std::string& cert, std::string& id, std::string& gpg_id)
{
RsCertificate crt(cert) ;
return AuthGPG::getAuthGPG()->LoadCertificateFromString(crt.armouredPGPKey(),id,gpg_id) ;
}
bool p3Peers::loadCertificateFromFile(const std::string &/*fname*/, std::string &/*id*/, std::string &/*gpg_id*/)
{
#ifdef P3PEERS_DEBUG
@ -1053,217 +874,49 @@ bool p3Peers::loadCertificateFromFile(const std::string &/*fname*/, std::string
return false;
}
//bool splitCerts(std::string in, std::string &sslcert, std::string &pgpcert)
//{
// std::cerr << "splitCerts():" << in;
// std::cerr << std::endl;
//
// /* search for -----END CERTIFICATE----- */
// std::string sslend("-----END CERTIFICATE-----");
// std::string pgpend("-----END PGP PUBLIC KEY BLOCK-----");
// size_t pos = in.find(sslend);
// size_t pos2 = in.find(pgpend);
// size_t ssllen, pgplen;
//
// if (pos != std::string::npos)
// {
// std::cerr << "splitCerts(): Found SSL Cert";
// std::cerr << std::endl;
//
// ssllen = pos + sslend.length();
// sslcert = in.substr(0, ssllen);
//
// if (pos2 != std::string::npos)
// {
// std::cerr << "splitCerts(): Found SSL + PGP Cert";
// std::cerr << std::endl;
//
// pgplen = pos2 + pgpend.length() - ssllen;
// pgpcert = in.substr(ssllen, pgplen);
// }
// return true;
// }
// else if (pos2 != std::string::npos)
// {
// std::cerr << "splitCerts(): Found PGP Cert Only";
// std::cerr << std::endl;
//
// pgplen = pos2 + pgpend.length();
// pgpcert = in.substr(0, pgplen);
// return true;
// }
// return false;
//}
static bool splitCert(const std::string &certstr, std::string &cert, std::string &peerInfo)
{
cert.erase();
peerInfo.erase();
/* search for -----END CERTIFICATE----- */
std::string pgpend("-----END PGP PUBLIC KEY BLOCK-----");
size_t pos = certstr.find(pgpend);
if (pos != std::string::npos) {
pos += pgpend.length();
cert = certstr.substr(0, pos);
if (pos + 1 < certstr.length())
peerInfo = certstr.substr(pos + 1);
}
return !cert.empty();
}
bool p3Peers::loadDetailsFromStringCert(const std::string &certstr, RsPeerDetails &pd,std::string& error_string)
{
#ifdef P3PEERS_DEBUG
std::cerr << "p3Peers::LoadCertificateFromString() ";
std::cerr << std::endl;
#endif
//parse the text to get ip address
try {
try
{
RsCertificate cert(certstr) ;
std::string cert;
std::string peerInfo;
if (splitCert(certstr, cert, peerInfo)) {
std::string gpg_id;
AuthGPG::getAuthGPG()->LoadCertificateFromString(cert, gpg_id,error_string);
AuthGPG::getAuthGPG()->getGPGDetails(gpg_id, pd);
if (gpg_id.empty()) {
if(!AuthGPG::getAuthGPG()->getGPGDetailsFromBinaryBlock(cert.pgp_key(),cert.pgp_key_size(), pd.gpg_id,pd.name,pd.gpgSigners))
return false;
}
} else {
return false;
}
#ifdef P3PEERS_DEBUG
#ifdef P3PEERS_DEBUG
std::cerr << "Parsing cert for sslid, location, ext and local address details. : " << certstr << std::endl;
#endif
#endif
//let's parse the ssl id
pd.isOnlyGPGdetail = true;
size_t parsePosition = peerInfo.find(CERT_SSL_ID);
std::cerr << "sslid position : " << parsePosition << std::endl;
if (parsePosition != std::string::npos) {
parsePosition += CERT_SSL_ID.length();
std::string subCert = peerInfo.substr(parsePosition);
parsePosition = subCert.find(";");
if (parsePosition != std::string::npos) {
std::string ssl_id = subCert.substr(0, parsePosition);
std::cerr << "SSL id : " << ssl_id << std::endl;
pd.id = ssl_id;
pd.id = cert.sslid_string() ;
pd.localAddr = cert.loc_ip_string();
pd.localPort = cert.loc_port_us();
pd.extAddr = cert.ext_ip_string();
pd.extPort = cert.ext_port_us();
pd.dyndns = cert.dns_string() ;
pd.isOnlyGPGdetail = pd.id.empty();
}
}
//let's parse the location
parsePosition = peerInfo.find(CERT_LOCATION);
std::cerr << "location position : " << parsePosition << std::endl;
if (parsePosition != std::string::npos) {
parsePosition += CERT_LOCATION.length();
std::string subCert = peerInfo.substr(parsePosition);
parsePosition = subCert.find(";");
if (parsePosition != std::string::npos) {
std::string location = subCert.substr(0, parsePosition);
std::cerr << "location : " << location << std::endl;
pd.location = location;
}
}
//let's parse ip local address
parsePosition = peerInfo.find(CERT_LOCAL_IP);
std::cerr << "local ip position : " << parsePosition << std::endl;
if (parsePosition != std::string::npos) {
parsePosition += CERT_LOCAL_IP.length();
std::string subCert = peerInfo.substr(parsePosition);
parsePosition = subCert.find(":");
if (parsePosition != std::string::npos) {
std::string local_ip = subCert.substr(0, parsePosition);
std::cerr << "Local Ip : " << local_ip << std::endl;
pd.localAddr = local_ip;
//let's parse local port
subCert = subCert.substr(parsePosition + 1);
parsePosition = subCert.find(";");
if (parsePosition != std::string::npos) {
std::string local_port = subCert.substr(0, parsePosition);
std::cerr << "Local port : " << local_port << std::endl;
sscanf(local_port.c_str(), "%hu", &pd.localPort);
}
}
}
//let's parse ip ext address
parsePosition = peerInfo.find(CERT_EXT_IP);
std::cerr << "Ext ip position : " << parsePosition << std::endl;
if (parsePosition != std::string::npos) {
parsePosition = parsePosition + CERT_EXT_IP.length();
std::string subCert = peerInfo.substr(parsePosition);
parsePosition = subCert.find(":");
if (parsePosition != std::string::npos) {
std::string ext_ip = subCert.substr(0, parsePosition);
std::cerr << "Ext Ip : " << ext_ip << std::endl;
pd.extAddr = ext_ip;
//let's parse ext port
subCert = subCert.substr(parsePosition + 1);
parsePosition = subCert.find(";");
if (parsePosition != std::string::npos) {
std::string ext_port = subCert.substr(0, parsePosition);
std::cerr << "Ext port : " << ext_port << std::endl;
sscanf(ext_port.c_str(), "%hu", &pd.extPort);
}
}
}
//let's parse DynDNS
parsePosition = peerInfo.find(CERT_DYNDNS);
std::cerr << "location DynDNS : " << parsePosition << std::endl;
if (parsePosition != std::string::npos) {
parsePosition += CERT_DYNDNS.length();
std::string subCert = peerInfo.substr(parsePosition);
parsePosition = subCert.find(";");
if (parsePosition != std::string::npos) {
std::string DynDNS = subCert.substr(0, parsePosition);
std::cerr << "DynDNS : " << DynDNS << std::endl;
pd.dyndns = DynDNS;
}
}
} catch (...) {
catch (...)
{
std::cerr << "ConnectFriendWizard : Parse ip address error." << std::endl;
return false ;
}
if (pd.gpg_id == "") {
if (pd.gpg_id == "")
return false;
} else {
else
return true;
}
}
bool p3Peers::cleanCertificate(const std::string &certstr, std::string &cleanCert,int& error_code)
{
std::string cert;
std::string peerInfo;
RsCertificate::Format format ;
if (splitCert(certstr, cert, peerInfo)) {
cleanCert = cleanUpCertificate(cert,error_code);
if (!cleanCert.empty()) {
if (!peerInfo.empty()) {
if (*cleanCert.rbegin() != '\n') {
cleanCert += "\n";
}
cleanCert += peerInfo;
}
return true;
}
}
return false;
return RsCertificate::cleanCertificate(certstr,cleanCert,format,error_code) ;
}
bool p3Peers::saveCertificateToFile(const std::string &id, const std::string &/*fname*/)

View File

@ -93,13 +93,16 @@ virtual bool getAllowTunnelConnection() ;
/* Auth Stuff */
// Get the invitation (GPG cert + local/ext address + SSL id for the given peer)
virtual std::string GetRetroshareInvite(const std::string& ssl_id,bool include_signatures);
virtual std::string GetRetroshareInvite(const std::string& ssl_id,bool include_signatures,bool old_format = false);
// same but for own id
virtual std::string GetRetroshareInvite(bool include_signatures);
virtual std::string GetRetroshareInvite(bool include_signatures,bool old_format = false);
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 cleanCertificate(const std::string &certstr, std::string &cleanCert,int& error_code);
virtual bool saveCertificateToFile(const std::string &id, const std::string &fname);
virtual std::string saveCertificateToString(const std::string &id);

View File

@ -1,7 +1,7 @@
#include <fstream>
#include "argstream.h"
#include <pqi/cleanupxpgp.h>
//#include <pqi/cleanupxpgp.h>
#include <pgp/rscertificate.h>
int main(int argc,char *argv[])
@ -41,12 +41,12 @@ int main(int argc,char *argv[])
std::string res2 ;
int err ;
res2 = cleanUpCertificate(res,err) ;
//res2 = cleanUpCertificate(res,err) ;
if(res2 == "")
std::cerr << "Error while cleaning: " << err << std::endl;
else
res = res2 ;
//if(res2 == "")
// std::cerr << "Error while cleaning: " << err << std::endl;
//else
// res = res2 ;
std::cerr << "Certificate after cleaning:" << std::endl;
std::cerr << "==========================================" << std::endl;

View File

@ -25,6 +25,8 @@
// Warning: never store references to a t_RsGenericIdType accross threads, since the
// cached string convertion is not thread safe.
//
#pragma once
#include <stdexcept>
#include <string>
#include <stdint.h>
@ -45,7 +47,7 @@ template<uint32_t ID_SIZE_IN_BYTES> class t_RsGenericIdType
// Converts to a std::string using cached value.
//
std::string toStdString() const ;
std::string toStdString(bool upper_case = true) const ;
const unsigned char *toByteArray() const { return &bytes[0] ; }
static const uint32_t SIZE_IN_BYTES = ID_SIZE_IN_BYTES ;
@ -65,16 +67,23 @@ template<uint32_t ID_SIZE_IN_BYTES> class t_RsGenericIdType
unsigned char bytes[ID_SIZE_IN_BYTES] ;
};
template<uint32_t ID_SIZE_IN_BYTES> std::string t_RsGenericIdType<ID_SIZE_IN_BYTES>::toStdString() const
template<uint32_t ID_SIZE_IN_BYTES> std::string t_RsGenericIdType<ID_SIZE_IN_BYTES>::toStdString(bool upper_case) const
{
static const char out[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ;
static const char outh[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' } ;
static const char outl[16] = { '0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f' } ;
std::string res(ID_SIZE_IN_BYTES*2,' ') ;
for(uint32_t j = 0; j < ID_SIZE_IN_BYTES; j++)
if(upper_case)
{
res[2*j ] = out[ (bytes[j]>>4) ] ;
res[2*j+1] = out[ bytes[j] & 0xf ] ;
res[2*j ] = outh[ (bytes[j]>>4) ] ;
res[2*j+1] = outh[ bytes[j] & 0xf ] ;
}
else
{
res[2*j ] = outl[ (bytes[j]>>4) ] ;
res[2*j+1] = outl[ bytes[j] & 0xf ] ;
}
return res ;

View File

@ -75,6 +75,7 @@ ConfCertDialog::ConfCertDialog(const std::string& id, QWidget *parent, Qt::WFlag
connect(ui.signKeyButton, SIGNAL(clicked()), this, SLOT(signGPGKey()));
connect(ui.trusthelpButton, SIGNAL(clicked()), this, SLOT(showHelpDialog()));
connect(ui._shouldAddSignatures_CB, SIGNAL(toggled(bool)), this, SLOT(loadInvitePage()));
connect(ui._useOldFormat_CB, SIGNAL(toggled(bool)), this, SLOT(loadInvitePage()));
MainWindow *w = MainWindow::getInstance();
if (w) {
@ -343,8 +344,7 @@ void ConfCertDialog::loadInvitePage()
return;
}
std::string invite = rsPeers->GetRetroshareInvite(detail.id,ui._shouldAddSignatures_CB->isChecked()) ; // this needs to be a SSL id
std::string invite = rsPeers->GetRetroshareInvite(detail.id,ui._shouldAddSignatures_CB->isChecked(),ui._useOldFormat_CB->isChecked()) ; // this needs to be a SSL id
ui.userCertificateText->setReadOnly(true);
ui.userCertificateText->setMinimumHeight(200);

View File

@ -18,6 +18,46 @@
<normaloff>:/images/rstray3.png</normaloff>:/images/rstray3.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<layout class="QGridLayout" name="_12">
<item row="0" column="0">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>311</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="applyButton">
<property name="toolTip">
<string>Apply and Close</string>
</property>
<property name="text">
<string>OK</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QTabWidget" name="stabWidget">
<property name="currentIndex">
@ -376,7 +416,7 @@
<number>0</number>
</property>
<item>
<widget class="AvatarWidget" name="avatar" native="true">
<widget class="AvatarWidget" name="avatar">
<property name="minimumSize">
<size>
<width>96</width>
@ -698,6 +738,8 @@ p, li { white-space: pre-wrap; }
<item>
<widget class="QTextEdit" name="userCertificateText"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="_shouldAddSignatures_CB">
<property name="text">
@ -705,49 +747,31 @@ p, li { white-space: pre-wrap; }
</property>
</widget>
</item>
</layout>
</widget>
<item>
<widget class="QCheckBox" name="_useOldFormat_CB">
<property name="text">
<string>Use old key format</string>
</property>
</widget>
</item>
<item row="1" column="0">
<layout class="QGridLayout" name="_12">
<item row="0" column="0">
<spacer>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>311</width>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="applyButton">
<property name="toolTip">
<string>Apply and Close</string>
</property>
<property name="text">
<string>OK</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>

View File

@ -105,7 +105,8 @@ void ConnectFriendWizard::setCertificate(const QString &certificate)
std::string error_string;
if (rsPeers->loadDetailsFromStringCert(certificate.toUtf8().constData(), peerDetails, error_string)) {
if (rsPeers->loadDetailsFromStringCert(certificate.toUtf8().constData(), peerDetails, error_string))
{
#ifdef FRIEND_WIZARD_DEBUG
std::cerr << "ConnectFriendWizard got id : " << peerDetails.id << "; gpg_id : " << peerDetails.gpg_id << std::endl;
#endif
@ -131,6 +132,7 @@ void ConnectFriendWizard::initializePage(int id)
case Page_Text:
connect(ui->userCertHelpButton, SIGNAL( clicked()), this, SLOT(showHelpUserCert()));
connect(ui->userCertIncludeSignaturesButton, SIGNAL(clicked()), this, SLOT(toggleSignatureState()));
connect(ui->userCertOldFormatButton, SIGNAL(clicked()), this, SLOT(toggleFormatState()));
connect(ui->userCertCopyButton, SIGNAL(clicked()), this, SLOT(copyCert()));
connect(ui->userCertSaveButton, SIGNAL(clicked()), this, SLOT(saveCert()));
connect(ui->userCertMailButton, SIGNAL(clicked()), this, SLOT(runEmailClient()));
@ -412,6 +414,19 @@ void ConnectFriendWizard::accept()
bool sign = ui->signGPGCheckBox->isChecked();
bool accept_connection = ui->acceptNoSignGPGCheckBox->isChecked();
if(accept_connection || sign)
{
std::string certstr = ui->friendCertEdit->toPlainText().toUtf8().constData();
std::string ssl_id, pgp_id ;
if(!rsPeers->loadCertificateFromString(certstr,ssl_id,pgp_id))
{
std::cerr << "ConnectFriendWizard::accept(): cannot load that certificate." << std::endl;
return ;
}
}
if (!peerDetails.gpg_id.empty()) {
if (sign) {
std::cerr << "ConclusionPage::validatePage() signing GPG key." << std::endl;
@ -457,13 +472,27 @@ void ConnectFriendWizard::accept()
void ConnectFriendWizard::updateOwnCert()
{
std::string invite = rsPeers->GetRetroshareInvite(ui->userCertIncludeSignaturesButton->isChecked());
std::string invite = rsPeers->GetRetroshareInvite(ui->userCertIncludeSignaturesButton->isChecked(),ui->userCertOldFormatButton->isChecked());
std::cerr << "TextPage() getting Invite: " << invite << std::endl;
ui->userCertEdit->setPlainText(QString::fromUtf8(invite.c_str()));
}
void ConnectFriendWizard::toggleFormatState()
{
if (ui->userCertOldFormatButton->isChecked())
{
ui->userCertOldFormatButton->setToolTip(tr("Use new certificate format (safer, more robust)"));
ui->userCertOldFormatButton->setIcon(QIcon(":/images/ledoff1.png")) ;
}
else
{
ui->userCertOldFormatButton->setToolTip(tr("Use old (backward compatible) certificate format"));
ui->userCertOldFormatButton->setIcon(QIcon(":/images/ledon1.png")) ;
}
updateOwnCert();
}
void ConnectFriendWizard::toggleSignatureState()
{
if (ui->userCertIncludeSignaturesButton->isChecked()) {
@ -508,6 +537,8 @@ void ConnectFriendWizard::cleanFriendCert()
}
QMessageBox::information(NULL, tr("Certificate cleaning error"), msg) ;
}
}
}

View File

@ -45,6 +45,7 @@ private slots:
/* TextPage */
void updateOwnCert();
void toggleSignatureState();
void toggleFormatState();
void runEmailClient();
void showHelpUserCert();
void copyCert();

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>454</width>
<height>370</height>
<width>572</width>
<height>517</height>
</rect>
</property>
<property name="windowTitle">
@ -76,7 +76,7 @@
<attribute name="pageId">
<string notr="true">ConnectFriendWizard::Page_Text</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QLabel" name="userCertLabel">
<property name="text">
@ -91,6 +91,7 @@
<property name="font">
<font>
<family>Courier New</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="lineWrapMode">
@ -99,10 +100,13 @@
<property name="readOnly">
<bool>true</bool>
</property>
<property name="tabStopWidth">
<number>80</number>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="userCertHelpButton">
<property name="sizePolicy">
@ -203,6 +207,42 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="userCertOldFormatButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>20</horstretch>
<verstretch>20</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Run Email program</string>
</property>
<property name="icon">
<iconset resource="../images.qrc">
<normaloff>:/images/ledon1.png</normaloff>:/images/ledon1.png</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
@ -221,6 +261,7 @@
<property name="font">
<font>
<family>Courier New</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="lineWrapMode">
@ -229,7 +270,7 @@
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="friendCertCleanButton">
<property name="sizePolicy">
@ -250,6 +291,19 @@
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>