mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-12-27 16:39:29 -05:00
- 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:
parent
64e171948c
commit
60f51c358c
@ -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 \
|
||||
|
@ -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 = "" ;
|
||||
|
@ -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 ;
|
||||
|
@ -35,47 +35,10 @@ bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::
|
||||
|
||||
Radix64::decode(radix_cert,keydata,len) ;
|
||||
|
||||
unsigned char *data = (unsigned char *)keydata ;
|
||||
size_t new_len ;
|
||||
findLengthOfMinimalKey((unsigned char *)keydata,len,new_len) ;
|
||||
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "Total size: " << len << std::endl;
|
||||
#endif
|
||||
|
||||
uint8_t packet_tag;
|
||||
uint32_t packet_length ;
|
||||
|
||||
// 2 - parse key data, only keep public key data, user id and self-signature.
|
||||
|
||||
bool public_key=false ;
|
||||
bool own_signature=false ;
|
||||
bool user_id=false ;
|
||||
|
||||
while(true)
|
||||
{
|
||||
PGPKeyParser::read_packetHeader(data,packet_tag,packet_length) ;
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "Header:" << std::endl;
|
||||
std::cerr << " Packet tag: " << (int)packet_tag << std::endl;
|
||||
std::cerr << " Packet length: " << packet_length << std::endl;
|
||||
#endif
|
||||
|
||||
data += packet_length ;
|
||||
|
||||
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_PUBLIC_KEY)
|
||||
public_key = true ;
|
||||
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_USER_ID)
|
||||
user_id = true ;
|
||||
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE)
|
||||
own_signature = true ;
|
||||
|
||||
if(public_key && own_signature && user_id)
|
||||
break ;
|
||||
|
||||
if( (uint64_t)data - (uint64_t)keydata >= len )
|
||||
break ;
|
||||
}
|
||||
|
||||
cleaned_certificate = makeArmouredKey((unsigned char*)keydata,(uint64_t)data - (uint64_t)keydata,version_string) ;
|
||||
cleaned_certificate = makeArmouredKey((unsigned char*)keydata,new_len,version_string) ;
|
||||
return true ;
|
||||
}
|
||||
catch(std::exception& e)
|
||||
@ -86,6 +49,51 @@ bool PGPKeyManagement::createMinimalKey(const std::string& pgp_certificate,std::
|
||||
}
|
||||
}
|
||||
|
||||
void PGPKeyManagement::findLengthOfMinimalKey(const unsigned char *keydata,size_t len,size_t& new_len)
|
||||
{
|
||||
unsigned char *data = (unsigned char *)keydata ;
|
||||
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "Total size: " << len << std::endl;
|
||||
#endif
|
||||
|
||||
uint8_t packet_tag;
|
||||
uint32_t packet_length ;
|
||||
|
||||
// 2 - parse key data, only keep public key data, user id and self-signature.
|
||||
|
||||
bool public_key=false ;
|
||||
bool own_signature=false ;
|
||||
bool user_id=false ;
|
||||
|
||||
while(true)
|
||||
{
|
||||
PGPKeyParser::read_packetHeader(data,packet_tag,packet_length) ;
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "Header:" << std::endl;
|
||||
std::cerr << " Packet tag: " << (int)packet_tag << std::endl;
|
||||
std::cerr << " Packet length: " << packet_length << std::endl;
|
||||
#endif
|
||||
|
||||
data += packet_length ;
|
||||
|
||||
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_PUBLIC_KEY)
|
||||
public_key = true ;
|
||||
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_USER_ID)
|
||||
user_id = true ;
|
||||
if(packet_tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE)
|
||||
own_signature = true ;
|
||||
|
||||
if(public_key && own_signature && user_id)
|
||||
break ;
|
||||
|
||||
if( (uint64_t)data - (uint64_t)keydata >= len )
|
||||
break ;
|
||||
}
|
||||
|
||||
new_len = (uint64_t)data - (uint64_t)keydata ;
|
||||
}
|
||||
|
||||
std::string PGPKeyParser::extractRadixPartFromArmouredKey(const std::string& pgp_certificate,std::string& version_string)
|
||||
{
|
||||
int n = pgp_certificate.length() ;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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) ;
|
||||
|
||||
|
@ -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,14 +528,15 @@ 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;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* import to GnuPG and other Certificates */
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
#include "authssl.h"
|
||||
#include "sslfns.h"
|
||||
#include "cleanupxpgp.h"
|
||||
|
||||
#include "pqinetwork.h"
|
||||
#include "authgpg.h"
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -73,12 +73,13 @@ const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_TUNNEL = 6;
|
||||
const uint32_t RS_PEER_CONNECTSTATE_CONNECTED_UNKNOWN = 7;
|
||||
|
||||
/* Error codes for certificate cleaning */
|
||||
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 ;
|
||||
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_NO_ERROR = 0x00 ;
|
||||
const int RS_PEER_CERT_CLEANING_CODE_UNKOWN_ERROR = 0x01 ;
|
||||
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;
|
||||
|
||||
|
@ -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,48 +814,56 @@ 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
|
||||
std::cerr << "p3Peers::GetRetroshareInvite()" << std::endl;
|
||||
#endif
|
||||
#ifdef P3PEERS_DEBUG
|
||||
std::cerr << "p3Peers::GetRetroshareInvite()" << std::endl;
|
||||
#endif
|
||||
|
||||
//add the sslid, location, ip local and external address after the signature
|
||||
RsPeerDetails Detail;
|
||||
std::string invite ;
|
||||
//add the sslid, location, ip local and external address after the signature
|
||||
RsPeerDetails Detail;
|
||||
std::string invite ;
|
||||
|
||||
if (getPeerDetails(ssl_id, Detail))
|
||||
{
|
||||
invite = AuthGPG::getAuthGPG()->SaveCertificateToString(Detail.gpg_id,include_signatures);
|
||||
if (getPeerDetails(ssl_id, Detail))
|
||||
{
|
||||
unsigned char *mem_block = NULL;
|
||||
size_t mem_block_size = 0;
|
||||
|
||||
if(!Detail.isOnlyGPGdetail)
|
||||
{
|
||||
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 + ";";
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!AuthGPG::getAuthGPG()->exportPublicKey(PGPIdType(Detail.gpg_id),mem_block,mem_block_size,false,include_signatures))
|
||||
{
|
||||
std::cerr << "Cannot output certificate for id \"" << Detail.gpg_id << "\". Sorry." << std::endl;
|
||||
return "" ;
|
||||
}
|
||||
|
||||
#ifdef P3PEERS_DEBUG
|
||||
std::cerr << "p3Peers::GetRetroshareInvite() returns : \n" << invite << std::endl;
|
||||
#endif
|
||||
return invite;
|
||||
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
|
||||
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
|
||||
{
|
||||
RsCertificate cert(certstr) ;
|
||||
|
||||
//parse the text to get ip address
|
||||
try {
|
||||
if(!AuthGPG::getAuthGPG()->getGPGDetailsFromBinaryBlock(cert.pgp_key(),cert.pgp_key_size(), pd.gpg_id,pd.name,pd.gpgSigners))
|
||||
return false;
|
||||
|
||||
std::string cert;
|
||||
std::string peerInfo;
|
||||
#ifdef P3PEERS_DEBUG
|
||||
std::cerr << "Parsing cert for sslid, location, ext and local address details. : " << certstr << std::endl;
|
||||
#endif
|
||||
|
||||
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()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
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();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::cerr << "ConnectFriendWizard : Parse ip address error." << std::endl;
|
||||
return false ;
|
||||
}
|
||||
|
||||
#ifdef P3PEERS_DEBUG
|
||||
std::cerr << "Parsing cert for sslid, location, ext and local address details. : " << certstr << std::endl;
|
||||
#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.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 (...) {
|
||||
std::cerr << "ConnectFriendWizard : Parse ip address error." << std::endl;
|
||||
}
|
||||
|
||||
if (pd.gpg_id == "") {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
if (pd.gpg_id == "")
|
||||
return false;
|
||||
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*/)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,17 +67,24 @@ 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++)
|
||||
{
|
||||
res[2*j ] = out[ (bytes[j]>>4) ] ;
|
||||
res[2*j+1] = out[ bytes[j] & 0xf ] ;
|
||||
}
|
||||
if(upper_case)
|
||||
{
|
||||
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 ;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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>
|
||||
@ -699,56 +739,40 @@ p, li { white-space: pre-wrap; }
|
||||
<widget class="QTextEdit" name="userCertificateText"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="_shouldAddSignatures_CB">
|
||||
<property name="text">
|
||||
<string>Include signatures</string>
|
||||
</property>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="_shouldAddSignatures_CB">
|
||||
<property name="text">
|
||||
<string>Include signatures</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="_useOldFormat_CB">
|
||||
<property name="text">
|
||||
<string>Use old key format</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<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>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
@ -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) ;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ private slots:
|
||||
/* TextPage */
|
||||
void updateOwnCert();
|
||||
void toggleSignatureState();
|
||||
void toggleFormatState();
|
||||
void runEmailClient();
|
||||
void showHelpUserCert();
|
||||
void copyCert();
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user