mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
exposed un-verified PGP signatures on GXS ids in GUI. Added auto-ban of GXS ids signed by a PGP ids that has already signed a large enough set of GXS ids. Still needs some GUI to change the threshold.
This commit is contained in:
parent
9a6bcf81d7
commit
9d9b790a3e
@ -66,6 +66,11 @@ bool PgpAuxUtilsImpl::getGPGAllList(std::list<RsPgpId> &ids)
|
||||
return AuthGPG::getAuthGPG()->getGPGAllList(ids);
|
||||
}
|
||||
|
||||
bool PgpAuxUtilsImpl::parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const
|
||||
{
|
||||
return AuthGPG::getAuthGPG()->parseSignature(sign,signlen,issuer);
|
||||
}
|
||||
|
||||
bool PgpAuxUtilsImpl::askForDeferredSelfSignature(const void *data,
|
||||
const uint32_t len,
|
||||
unsigned char *sign,
|
||||
|
@ -41,10 +41,9 @@ class PgpAuxUtils
|
||||
virtual bool getGPGAllList(std::list<RsPgpId> &ids) = 0;
|
||||
virtual bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const = 0;
|
||||
|
||||
virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const =0;
|
||||
virtual bool VerifySignBin(const void *data, uint32_t len, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint) = 0;
|
||||
virtual bool askForDeferredSelfSignature(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,int& signature_result ) = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
class PgpAuxUtilsImpl: public PgpAuxUtils
|
||||
@ -55,6 +54,7 @@ public:
|
||||
virtual const RsPgpId &getPGPOwnId();
|
||||
virtual RsPgpId getPGPId(const RsPeerId& sslid);
|
||||
|
||||
virtual bool parseSignature(unsigned char *sign, unsigned int signlen, RsPgpId& issuer) const ;
|
||||
virtual bool getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) const;
|
||||
virtual bool VerifySignBin(const void *data, uint32_t len, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint);
|
||||
virtual bool getGPGAllList(std::list<RsPgpId> &ids);
|
||||
|
@ -1692,6 +1692,24 @@ bool PGPHandler::mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src)
|
||||
return to_add.size() > 0 ;
|
||||
}
|
||||
|
||||
bool PGPHandler::parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id)
|
||||
{
|
||||
uint64_t issuer ;
|
||||
|
||||
if(!PGPKeyManagement::parseSignature(sign,signlen,issuer))
|
||||
return false ;
|
||||
|
||||
unsigned char bytes[8] ;
|
||||
for(int i=0;i<8;++i)
|
||||
{
|
||||
bytes[7-i] = issuer & 0xff ;
|
||||
issuer >>= 8 ;
|
||||
}
|
||||
issuer_id = RsPgpId(bytes) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool PGPHandler::privateTrustCertificate(const RsPgpId& id,int trustlvl)
|
||||
{
|
||||
if(trustlvl < 0 || trustlvl >= 6 || trustlvl == 1)
|
||||
|
@ -74,7 +74,7 @@ class PGPHandler
|
||||
bool haveSecretKey(const RsPgpId& id) const ;
|
||||
|
||||
bool importGPGKeyPair(const std::string& filename,RsPgpId& imported_id,std::string& import_error) ;
|
||||
bool importGPGKeyPairFromString(const std::string& data,RsPgpId& imported_id,std::string& import_error) ;
|
||||
bool importGPGKeyPairFromString(const std::string& data,RsPgpId& imported_id,std::string& import_error) ;
|
||||
bool exportGPGKeyPair(const std::string& filename,const RsPgpId& exported_id) const ;
|
||||
|
||||
bool availableGPGCertificatesWithPrivateKeys(std::list<RsPgpId>& ids);
|
||||
@ -85,6 +85,7 @@ class PGPHandler
|
||||
std::string SaveCertificateToString(const RsPgpId& id,bool include_signatures) const ;
|
||||
bool exportPublicKey(const RsPgpId& id,unsigned char *& mem,size_t& mem_size,bool armoured,bool include_signatures) const ;
|
||||
|
||||
bool parseSignature(unsigned char *sign, unsigned int signlen,RsPgpId& issuer_id) ;
|
||||
bool SignDataBin(const RsPgpId& id,const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen,bool make_raw_signature=false) ;
|
||||
bool VerifySignBin(const void *data, uint32_t data_len, unsigned char *sign, unsigned int sign_len, const PGPFingerprintType& withfingerprint) ;
|
||||
bool privateSignCertificate(const RsPgpId& own_id,const RsPgpId& id_of_key_to_sign) ;
|
||||
@ -110,7 +111,7 @@ class PGPHandler
|
||||
// Removes the given keys from the keyring. Also backup the keyring to a file which name is automatically generated
|
||||
// and given pack for proper display.
|
||||
//
|
||||
bool removeKeysFromPGPKeyring(const std::set<RsPgpId>& key_ids,std::string& backup_file,uint32_t& error_code) ;
|
||||
bool removeKeysFromPGPKeyring(const std::set<RsPgpId>& key_ids,std::string& backup_file,uint32_t& error_code) ;
|
||||
|
||||
//bool isKeySupported(const RsPgpId& id) const ;
|
||||
|
||||
|
@ -157,7 +157,75 @@ uint32_t PGPKeyManagement::compute24bitsCRC(unsigned char *octets, size_t len)
|
||||
crc ^= PGP_CRC24_POLY;
|
||||
}
|
||||
}
|
||||
return crc & 0xFFFFFFL;
|
||||
return crc & 0xFFFFFFL;
|
||||
}
|
||||
|
||||
bool PGPKeyManagement::parseSignature(const unsigned char *signature, size_t sign_len, uint64_t& issuer)
|
||||
{
|
||||
unsigned char *data = (unsigned char *)signature ;
|
||||
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << "Total size: " << len << std::endl;
|
||||
#endif
|
||||
|
||||
uint8_t packet_tag;
|
||||
uint32_t packet_length ;
|
||||
|
||||
PGPKeyParser::read_packetHeader(data,packet_tag,packet_length) ;
|
||||
|
||||
std::cerr << "Packet tag : " << (int)packet_tag << ", length=" << packet_length << std::endl;
|
||||
|
||||
// 2 - parse key data, only keep public key data, user id and self-signature.
|
||||
|
||||
bool issuer_found=false ;
|
||||
|
||||
if(sign_len < 12) // conservative check to allow the explicit reads below, until header of first sub-packet
|
||||
return false ;
|
||||
|
||||
unsigned char signature_type = data[0] ;
|
||||
|
||||
if(signature_type != 4)
|
||||
return false ;
|
||||
|
||||
data += 1 ; // skip version number
|
||||
data += 1 ; // skip signature type
|
||||
data += 1 ; // skip public key algorithm
|
||||
data += 1 ; // skip hash algorithm
|
||||
|
||||
uint32_t hashed_size = 256u*data[0] + data[1] ;
|
||||
data += 2 ;
|
||||
|
||||
// now read hashed sub-packets
|
||||
|
||||
uint8_t *start_hashed_data = data ;
|
||||
|
||||
while(true)
|
||||
{
|
||||
int subpacket_size = PGPKeyParser::read_125Size(data) ; // following RFC4880
|
||||
uint8_t subpacket_type = data[0] ; data+=1 ;
|
||||
|
||||
#ifdef DEBUG_PGPUTIL
|
||||
std::cerr << " SubPacket tag: " << (int)subpacket_type << std::endl;
|
||||
std::cerr << " SubPacket length: " << subpacket_size << std::endl;
|
||||
#endif
|
||||
|
||||
if(subpacket_type == PGPKeyParser::PGP_PACKET_TAG_ISSUER && subpacket_size == 9)
|
||||
{
|
||||
issuer_found = true ;
|
||||
issuer = PGPKeyParser::read_KeyID(data) ;
|
||||
}
|
||||
else
|
||||
data += subpacket_size-1 ; // we remove the size of subpacket type
|
||||
|
||||
if(issuer_found)
|
||||
break ;
|
||||
|
||||
if( (uint64_t)data - (uint64_t)start_hashed_data >= hashed_size )
|
||||
break ;
|
||||
}
|
||||
// non hashed sub-packets are ignored for now.
|
||||
|
||||
return issuer_found ;
|
||||
}
|
||||
|
||||
uint64_t PGPKeyParser::read_KeyID(unsigned char *& data)
|
||||
|
@ -65,6 +65,8 @@ class PGPKeyManagement
|
||||
// Computes the 24 bits CRC checksum necessary to all PGP data.
|
||||
//
|
||||
static uint32_t compute24bitsCRC(unsigned char *data,size_t len) ;
|
||||
|
||||
static bool parseSignature(const unsigned char *signature, size_t sign_len, uint64_t &issuer) ;
|
||||
};
|
||||
|
||||
// This class handles the parsing of PGP packet headers under various (old and new) formats.
|
||||
@ -75,6 +77,7 @@ class PGPKeyParser
|
||||
static const uint8_t PGP_PACKET_TAG_PUBLIC_KEY = 6 ;
|
||||
static const uint8_t PGP_PACKET_TAG_USER_ID = 13 ;
|
||||
static const uint8_t PGP_PACKET_TAG_SIGNATURE = 2 ;
|
||||
static const uint8_t PGP_PACKET_TAG_ISSUER = 16 ;
|
||||
|
||||
// These functions read and move the data pointer to the next byte after the read section.
|
||||
//
|
||||
|
@ -308,6 +308,11 @@ bool AuthGPG::VerifySignature(const void *data, int datalen, const void *sig, un
|
||||
return PGPHandler::VerifySignBin((unsigned char*)data,datalen,(unsigned char*)sig,siglen,withfingerprint) ;
|
||||
}
|
||||
|
||||
bool AuthGPG::parseSignature(const void *sig, unsigned int siglen, RsPgpId& issuer_id)
|
||||
{
|
||||
return PGPHandler::parseSignature((unsigned char*)sig,siglen,issuer_id) ;
|
||||
}
|
||||
|
||||
bool AuthGPG::exportProfile(const std::string& fname,const RsPgpId& exported_id)
|
||||
{
|
||||
return PGPHandler::exportGPGKeyPair(fname,exported_id) ;
|
||||
|
@ -210,6 +210,7 @@ class AuthGPG: public p3Config, public RsTickingThread, public PGPHandler
|
||||
****/
|
||||
virtual bool SignDataBin(const void *data, const uint32_t len, unsigned char *sign, unsigned int *signlen);
|
||||
virtual bool VerifySignBin(const void*, uint32_t, unsigned char*, unsigned int, const PGPFingerprintType& withfingerprint);
|
||||
virtual bool parseSignature(const void *sig, unsigned int siglen, RsPgpId& issuer_id);
|
||||
|
||||
virtual bool encryptDataBin(const RsPgpId& pgp_id,const void *data, const uint32_t len, unsigned char *encr, unsigned int *encrlen);
|
||||
virtual bool decryptDataBin(const void *data, const uint32_t len, unsigned char *decr, unsigned int *decrlen);
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "services/p3gxsreputation.h"
|
||||
#include "serialiser/rsgxsreputationitems.h"
|
||||
#include "serialiser/rsconfigitems.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
@ -38,6 +39,7 @@
|
||||
/****
|
||||
* #define DEBUG_REPUTATION 1
|
||||
****/
|
||||
#define DEBUG_REPUTATION 1
|
||||
|
||||
/************ IMPLEMENTATION NOTES *********************************
|
||||
*
|
||||
@ -134,7 +136,9 @@ static const int ACTIVE_FRIENDS_ONLINE_DELAY = 86400*7 ; // 1 week.
|
||||
static const int kReputationRequestPeriod = 600; // 10 mins
|
||||
static const int kReputationStoreWait = 180; // 3 minutes.
|
||||
static const float REPUTATION_ASSESSMENT_THRESHOLD_X1 = 0.5f ; // reputation under which the peer gets killed
|
||||
|
||||
static const uint32_t PGP_AUTO_BAN_THRESHOLD_DEFAULT = 2 ; // above this, auto ban any GXS id signed by this node
|
||||
static const uint32_t IDENTITY_FLAGS_UPDATE_DELAY = 100 ; //
|
||||
static const uint32_t BANNED_NODES_UPDATE_DELAY = 613 ; // update approx every 10 mins. Chosen to not be a multiple of IDENTITY_FLAGS_UPDATE_DELAY
|
||||
|
||||
p3GxsReputation::p3GxsReputation(p3LinkMgr *lm)
|
||||
:p3Service(), p3Config(),
|
||||
@ -142,11 +146,13 @@ p3GxsReputation::p3GxsReputation(p3LinkMgr *lm)
|
||||
{
|
||||
addSerialType(new RsGxsReputationSerialiser());
|
||||
|
||||
mPgpAutoBanThreshold = PGP_AUTO_BAN_THRESHOLD_DEFAULT ;
|
||||
mRequestTime = 0;
|
||||
mStoreTime = 0;
|
||||
mReputationsUpdated = false;
|
||||
mLastActiveFriendsUpdate = 0 ;
|
||||
mAverageActiveFriends = 0 ;
|
||||
mLastBannedNodesUpdate = 0 ;
|
||||
}
|
||||
|
||||
const std::string GXS_REPUTATION_APP_NAME = "gxsreputation";
|
||||
@ -181,15 +187,22 @@ int p3GxsReputation::tick()
|
||||
}
|
||||
|
||||
static time_t last_identity_flags_update = 0 ;
|
||||
static time_t last_banned_nodes_update = 0 ;
|
||||
|
||||
// no more than once per 5 second chunk.
|
||||
|
||||
if(now > 100+last_identity_flags_update)
|
||||
if(now > IDENTITY_FLAGS_UPDATE_DELAY+last_identity_flags_update)
|
||||
{
|
||||
last_identity_flags_update = now ;
|
||||
|
||||
updateIdentityFlags() ;
|
||||
}
|
||||
if(now > BANNED_NODES_UPDATE_DELAY+mLastBannedNodesUpdate) // 613 is not a multiple of 100, to avoid piling up work
|
||||
{
|
||||
mLastBannedNodesUpdate = now ;
|
||||
|
||||
updateBannedNodesList();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
static time_t last_debug_print = time(NULL) ;
|
||||
@ -203,10 +216,64 @@ int p3GxsReputation::tick()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void p3GxsReputation::setNodeAutoBanThreshold(uint32_t n)
|
||||
{
|
||||
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
|
||||
|
||||
if(n != mPgpAutoBanThreshold)
|
||||
{
|
||||
mLastBannedNodesUpdate = 0 ;
|
||||
mPgpAutoBanThreshold = n ;
|
||||
IndicateConfigChanged() ;
|
||||
}
|
||||
}
|
||||
uint32_t p3GxsReputation::nodeAutoBanThreshold()
|
||||
{
|
||||
return mPgpAutoBanThreshold ;
|
||||
}
|
||||
|
||||
int p3GxsReputation::status()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
class ZeroInitCnt
|
||||
{
|
||||
public:
|
||||
ZeroInitCnt(): cnt(0) {}
|
||||
uint32_t cnt ;
|
||||
|
||||
operator uint32_t& () { return cnt ; }
|
||||
operator uint32_t() const { return cnt ; }
|
||||
};
|
||||
|
||||
void p3GxsReputation::updateBannedNodesList()
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "Updating PGP ban list based on signed GxsIds to ban" << std::endl;
|
||||
#endif
|
||||
std::map<RsGxsId, Reputation> tmpreps ;
|
||||
|
||||
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
|
||||
tmpreps = mReputations ;
|
||||
|
||||
std::map<RsPgpId,ZeroInitCnt> pgp_ids_to_ban ;
|
||||
|
||||
for( std::map<RsGxsId, Reputation>::iterator rit = tmpreps.begin();rit!=tmpreps.end();++rit)
|
||||
if((rit->second.mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_LINKED) && rit->second.mOwnOpinion == p3GxsReputation::OPINION_NEGATIVE)
|
||||
++pgp_ids_to_ban[rit->second.mOwnerNode] ;
|
||||
|
||||
mBannedPgpIds.clear() ;
|
||||
|
||||
if(mPgpAutoBanThreshold > 0)
|
||||
for(std::map<RsPgpId,ZeroInitCnt>::const_iterator it(pgp_ids_to_ban.begin());it!=pgp_ids_to_ban.end();++it)
|
||||
{
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "PGP Id: " << it->first << ". Ban count=" << it->second << " - " << (( it->second >= mPgpAutoBanThreshold)?"Banned!":"OK" ) << std::endl;
|
||||
#endif
|
||||
if(it->second >= mPgpAutoBanThreshold)
|
||||
mBannedPgpIds.insert(it->first) ;
|
||||
}
|
||||
}
|
||||
|
||||
void p3GxsReputation::updateIdentityFlags()
|
||||
{
|
||||
@ -248,7 +315,11 @@ void p3GxsReputation::updateIdentityFlags()
|
||||
}
|
||||
it->second.mIdentityFlags = 0 ;
|
||||
|
||||
if(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED) it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_LINKED ;
|
||||
if(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)
|
||||
{
|
||||
it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_LINKED ;
|
||||
it->second.mOwnerNode = details.mPgpId ;
|
||||
}
|
||||
if(details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN ) it->second.mIdentityFlags |= REPUTATION_IDENTITY_FLAG_PGP_KNOWN ;
|
||||
|
||||
#ifdef DEBUG_REPUTATION
|
||||
@ -614,6 +685,13 @@ bool p3GxsReputation::getReputationInfo(const RsGxsId& gxsid, RsReputations::Rep
|
||||
info.mOverallReputationScore = rep.mReputation ;
|
||||
info.mFriendAverage = rep.mFriendAverage ;
|
||||
|
||||
if( (rep.mIdentityFlags & REPUTATION_IDENTITY_FLAG_PGP_LINKED) && (mBannedPgpIds.find(rep.mOwnerNode) != mBannedPgpIds.end()))
|
||||
{
|
||||
info.mAssessment = RsReputations::ASSESSMENT_BAD ;
|
||||
std::cerr << "p3GxsReputations: identity " << gxsid << " is banned because owner node ID " << rep.mOwnerNode << " is banned." << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(info.mOverallReputationScore > REPUTATION_ASSESSMENT_THRESHOLD_X1)
|
||||
info.mAssessment = RsReputations::ASSESSMENT_OK ;
|
||||
else
|
||||
@ -693,6 +771,7 @@ bool p3GxsReputation::setOwnOpinion(const RsGxsId& gxsid, const RsReputations::O
|
||||
mUpdated.insert(std::make_pair(now, gxsid));
|
||||
mUpdatedReputations.insert(gxsid);
|
||||
mReputationsUpdated = true;
|
||||
mLastBannedNodesUpdate = 0 ; // for update of banned nodes
|
||||
|
||||
// Switched to periodic save due to scale of data.
|
||||
IndicateConfigChanged();
|
||||
@ -709,6 +788,7 @@ RsSerialiser *p3GxsReputation::setupSerialiser()
|
||||
{
|
||||
RsSerialiser *rss = new RsSerialiser ;
|
||||
rss->addSerialType(new RsGxsReputationSerialiser());
|
||||
rss->addSerialType(new RsGeneralConfigSerialiser());
|
||||
return rss ;
|
||||
}
|
||||
|
||||
@ -757,6 +837,15 @@ bool p3GxsReputation::saveList(bool& cleanup, std::list<RsItem*> &savelist)
|
||||
savelist.push_back(item);
|
||||
count++;
|
||||
}
|
||||
|
||||
RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ;
|
||||
RsTlvKeyValue kv;
|
||||
kv.key = "AUTO_BAN_NODES_THRESHOLD" ;
|
||||
rs_sprintf(kv.value, "%d", mPgpAutoBanThreshold);
|
||||
vitem->tlvkvs.pairs.push_back(kv) ;
|
||||
|
||||
savelist.push_back(vitem) ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -770,35 +859,52 @@ bool p3GxsReputation::loadList(std::list<RsItem *>& loadList)
|
||||
#ifdef DEBUG_REPUTATION
|
||||
std::cerr << "p3GxsReputation::saveList()" << std::endl;
|
||||
#endif
|
||||
std::list<RsItem *>::iterator it;
|
||||
std::set<RsPeerId> peerSet;
|
||||
std::list<RsItem *>::iterator it;
|
||||
std::set<RsPeerId> peerSet;
|
||||
|
||||
for(it = loadList.begin(); it != loadList.end(); ++it)
|
||||
{
|
||||
RsGxsReputationConfigItem *item = dynamic_cast<RsGxsReputationConfigItem *>(*it);
|
||||
for(it = loadList.begin(); it != loadList.end(); ++it)
|
||||
{
|
||||
RsGxsReputationConfigItem *item = dynamic_cast<RsGxsReputationConfigItem *>(*it);
|
||||
|
||||
// Configurations are loaded first. (to establish peerSet).
|
||||
if (item)
|
||||
{
|
||||
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
|
||||
RsPeerId peerId(item->mPeerId);
|
||||
ReputationConfig &config = mConfig[peerId];
|
||||
config.mPeerId = peerId;
|
||||
config.mLatestUpdate = item->mLatestUpdate;
|
||||
config.mLastQuery = 0;
|
||||
// Configurations are loaded first. (to establish peerSet).
|
||||
if (item)
|
||||
{
|
||||
RsStackMutex stack(mReputationMtx); /****** LOCKED MUTEX *******/
|
||||
RsPeerId peerId(item->mPeerId);
|
||||
ReputationConfig &config = mConfig[peerId];
|
||||
config.mPeerId = peerId;
|
||||
config.mLatestUpdate = item->mLatestUpdate;
|
||||
config.mLastQuery = 0;
|
||||
|
||||
peerSet.insert(peerId);
|
||||
}
|
||||
peerSet.insert(peerId);
|
||||
}
|
||||
|
||||
RsGxsReputationSetItem *set = dynamic_cast<RsGxsReputationSetItem *>(*it);
|
||||
if (set)
|
||||
loadReputationSet(set, peerSet);
|
||||
RsGxsReputationSetItem *set = dynamic_cast<RsGxsReputationSetItem *>(*it);
|
||||
if (set)
|
||||
loadReputationSet(set, peerSet);
|
||||
|
||||
delete (*it);
|
||||
}
|
||||
RsConfigKeyValueSet *vitem = dynamic_cast<RsConfigKeyValueSet *>(*it);
|
||||
|
||||
if(vitem)
|
||||
for(std::list<RsTlvKeyValue>::const_iterator kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit)
|
||||
{
|
||||
if(kit->key == "AUTO_BAN_NODES_THRESHOLD")
|
||||
{
|
||||
int val ;
|
||||
if (sscanf(kit->value.c_str(), "%d", &val) == 1)
|
||||
{
|
||||
mPgpAutoBanThreshold = val ;
|
||||
std::cerr << "Setting AutoBanNode threshold to " << val << std::endl ;
|
||||
mLastBannedNodesUpdate = 0 ; // force update
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
delete (*it);
|
||||
}
|
||||
|
||||
loadList.clear() ;
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool p3GxsReputation::loadReputationSet(RsGxsReputationSetItem *item, const std::set<RsPeerId> &peerSet)
|
||||
|
@ -77,6 +77,8 @@ public:
|
||||
float mFriendAverage ;
|
||||
float mReputation;
|
||||
|
||||
RsPgpId mOwnerNode;
|
||||
|
||||
uint32_t mIdentityFlags;
|
||||
};
|
||||
|
||||
@ -98,6 +100,9 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations /
|
||||
virtual bool getReputationInfo(const RsGxsId& id,ReputationInfo& info) ;
|
||||
virtual bool isIdentityBanned(const RsGxsId& id) ;
|
||||
|
||||
virtual void setNodeAutoBanThreshold(uint32_t n) ;
|
||||
virtual uint32_t nodeAutoBanThreshold() ;
|
||||
|
||||
/***** overloaded from p3Service *****/
|
||||
virtual int tick();
|
||||
virtual int status();
|
||||
@ -112,7 +117,7 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations /
|
||||
virtual void saveDone();
|
||||
virtual bool loadList(std::list<RsItem*>& load) ;
|
||||
|
||||
private:
|
||||
private:
|
||||
|
||||
bool processIncoming();
|
||||
|
||||
@ -120,6 +125,7 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations /
|
||||
bool RecvReputations(RsGxsReputationUpdateItem *item);
|
||||
bool updateLatestUpdate(RsPeerId peerid, time_t latest_update);
|
||||
void updateActiveFriends() ;
|
||||
void updateBannedNodesList();
|
||||
|
||||
// internal update of data. Takes care of cleaning empty boxes.
|
||||
void locked_updateOpinion(const RsPeerId &from, const RsGxsId &about, RsReputations::Opinion op);
|
||||
@ -138,6 +144,7 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations /
|
||||
time_t mLastActiveFriendsUpdate;
|
||||
time_t mRequestTime;
|
||||
time_t mStoreTime;
|
||||
time_t mLastBannedNodesUpdate ;
|
||||
bool mReputationsUpdated;
|
||||
uint32_t mAverageActiveFriends ;
|
||||
|
||||
@ -149,7 +156,11 @@ class p3GxsReputation: public p3Service, public p3Config, public RsReputations /
|
||||
std::multimap<time_t, RsGxsId> mUpdated;
|
||||
|
||||
// set of Reputations to send to p3IdService.
|
||||
std::set<RsGxsId> mUpdatedReputations;
|
||||
std::set<RsGxsId> mUpdatedReputations;
|
||||
|
||||
// PGP Ids auto-banned. This is updated regularly.
|
||||
std::set<RsPgpId> mBannedPgpIds ;
|
||||
uint32_t mPgpAutoBanThreshold ;
|
||||
};
|
||||
|
||||
#endif //SERVICE_RSGXSREPUTATION_HEADER
|
||||
|
@ -59,6 +59,7 @@
|
||||
#define GXSID_MAX_CACHE_SIZE 5000
|
||||
|
||||
static const uint32_t MAX_KEEP_UNUSED_KEYS = 30*86400 ; // remove unused keys after 30 days
|
||||
static const uint32_t MAX_KEEP_BANNED_KEYS = 30*86400 ; // remove banned keys after 5 days
|
||||
static const uint32_t MAX_DELAY_BEFORE_CLEANING = 601 ; // clean old keys every 10 mins
|
||||
|
||||
RsIdentity *rsIdentity = NULL;
|
||||
@ -312,21 +313,25 @@ void p3IdService::cleanUnusedKeys()
|
||||
|
||||
// we need to stash all ids to delete into an off-mutex structure since deleteIdentity() will trigger the lock
|
||||
{
|
||||
RS_STACK_MUTEX(mIdMtx) ;
|
||||
RS_STACK_MUTEX(mIdMtx) ;
|
||||
|
||||
if(!mOwnIdsLoaded)
|
||||
{
|
||||
std::cerr << "(EE) Own ids not loaded. Cannot clean unused keys." << std::endl;
|
||||
return ;
|
||||
}
|
||||
if(!mOwnIdsLoaded)
|
||||
{
|
||||
std::cerr << "(EE) Own ids not loaded. Cannot clean unused keys." << std::endl;
|
||||
return ;
|
||||
}
|
||||
|
||||
// grab at most 10 identities to delete. No need to send too many requests to the token queue at once.
|
||||
time_t now = time(NULL) ;
|
||||
int n=0 ;
|
||||
// grab at most 10 identities to delete. No need to send too many requests to the token queue at once.
|
||||
time_t now = time(NULL) ;
|
||||
int n=0 ;
|
||||
|
||||
for(std::map<RsGxsId,time_t>::iterator it(mKeysTS.begin());it!=mKeysTS.end() && n < 10;++it)
|
||||
if(it->second + MAX_KEEP_UNUSED_KEYS < now && std::find(mOwnIds.begin(),mOwnIds.end(),it->first) == mOwnIds.end())
|
||||
ids_to_delete.push_back(it->first),++n ;
|
||||
for(std::map<RsGxsId,time_t>::iterator it(mKeysTS.begin());it!=mKeysTS.end() && n < 10;++it)
|
||||
{
|
||||
if(it->second + MAX_KEEP_UNUSED_KEYS < now && std::find(mOwnIds.begin(),mOwnIds.end(),it->first) == mOwnIds.end())
|
||||
ids_to_delete.push_back(it->first),++n ;
|
||||
else if(it->second + MAX_KEEP_BANNED_KEYS < now && rsReputations->isIdentityBanned(it->first))
|
||||
ids_to_delete.push_back(it->first),++n ;
|
||||
}
|
||||
}
|
||||
|
||||
for(std::list<RsGxsId>::const_iterator it(ids_to_delete.begin());it!=ids_to_delete.end();++it)
|
||||
@ -1023,7 +1028,7 @@ bool p3IdService::opinion_handlerequest(uint32_t token)
|
||||
|
||||
// update IdScore too.
|
||||
bool pgpId = (meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID);
|
||||
ssdata.score.rep.updateIdScore(pgpId, ssdata.pgp.idKnown);
|
||||
ssdata.score.rep.updateIdScore(pgpId, ssdata.pgp.validatedSignature);
|
||||
ssdata.score.rep.update();
|
||||
|
||||
/* save string */
|
||||
@ -1089,7 +1094,7 @@ bool p3IdService::getGroupData(const uint32_t &token, std::vector<RsGxsIdGroup>
|
||||
SSGxsIdGroup ssdata;
|
||||
if (ssdata.load(group.mMeta.mServiceString))
|
||||
{
|
||||
group.mPgpKnown = ssdata.pgp.idKnown;
|
||||
group.mPgpKnown = ssdata.pgp.validatedSignature;
|
||||
group.mPgpId = ssdata.pgp.pgpId;
|
||||
group.mReputation = ssdata.score.rep;
|
||||
#ifdef DEBUG_IDS
|
||||
@ -1282,7 +1287,16 @@ bool SSGxsIdPgp::load(const std::string &input)
|
||||
uint32_t attempts = 0;
|
||||
if (1 == sscanf(input.c_str(), "K:1 I:%[^)]", pgpline))
|
||||
{
|
||||
idKnown = true;
|
||||
validatedSignature = true;
|
||||
std::string str_line = pgpline;
|
||||
pgpId = RsPgpId(str_line);
|
||||
return true;
|
||||
}
|
||||
else if (3 == sscanf(input.c_str(), "K:0 T:%d C:%d I:%[^)]", ×tamp, &attempts,pgpline))
|
||||
{
|
||||
lastCheckTs = timestamp;
|
||||
checkAttempts = attempts;
|
||||
validatedSignature = false;
|
||||
std::string str_line = pgpline;
|
||||
pgpId = RsPgpId(str_line);
|
||||
return true;
|
||||
@ -1291,21 +1305,21 @@ bool SSGxsIdPgp::load(const std::string &input)
|
||||
{
|
||||
lastCheckTs = timestamp;
|
||||
checkAttempts = attempts;
|
||||
idKnown = false;
|
||||
validatedSignature = false;
|
||||
return true;
|
||||
}
|
||||
else if (1 == sscanf(input.c_str(), "K:0 T:%d", ×tamp))
|
||||
{
|
||||
lastCheckTs = timestamp;
|
||||
checkAttempts = 0;
|
||||
idKnown = false;
|
||||
validatedSignature = false;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
lastCheckTs = 0;
|
||||
checkAttempts = 0;
|
||||
idKnown = false;
|
||||
validatedSignature = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1313,7 +1327,7 @@ bool SSGxsIdPgp::load(const std::string &input)
|
||||
std::string SSGxsIdPgp::save() const
|
||||
{
|
||||
std::string output;
|
||||
if (idKnown)
|
||||
if (validatedSignature)
|
||||
{
|
||||
output += "K:1 I:";
|
||||
output += pgpId.toStdString();
|
||||
@ -1321,6 +1335,9 @@ std::string SSGxsIdPgp::save() const
|
||||
else
|
||||
{
|
||||
rs_sprintf(output, "K:0 T:%d C:%d", lastCheckTs, checkAttempts);
|
||||
|
||||
if(!pgpId.isNull())
|
||||
output += " I:"+pgpId.toStdString();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@ -1663,9 +1680,9 @@ void RsGxsIdCache::updateServiceString(std::string serviceString)
|
||||
{
|
||||
if (details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)
|
||||
{
|
||||
if(ssdata.pgp.idKnown) details.mFlags |= RS_IDENTITY_FLAGS_PGP_KNOWN ;
|
||||
if(ssdata.pgp.validatedSignature) details.mFlags |= RS_IDENTITY_FLAGS_PGP_KNOWN ;
|
||||
|
||||
if (details.mFlags & RS_IDENTITY_FLAGS_PGP_KNOWN)
|
||||
if (details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED)
|
||||
details.mPgpId = ssdata.pgp.pgpId;
|
||||
else
|
||||
details.mPgpId.clear();
|
||||
@ -2800,7 +2817,7 @@ bool p3IdService::pgphash_handlerequest(uint32_t token)
|
||||
SSGxsIdGroup ssdata;
|
||||
if (ssdata.load(vit->mMeta.mServiceString))
|
||||
{
|
||||
if (ssdata.pgp.idKnown)
|
||||
if (ssdata.pgp.validatedSignature)
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "p3IdService::pgphash_request() discarding Already Known";
|
||||
@ -2919,7 +2936,7 @@ bool p3IdService::pgphash_process()
|
||||
#endif // DEBUG_IDS
|
||||
|
||||
/* update */
|
||||
ssdata.pgp.idKnown = true;
|
||||
ssdata.pgp.validatedSignature = true;
|
||||
ssdata.pgp.pgpId = pgpId;
|
||||
|
||||
}
|
||||
@ -2939,12 +2956,13 @@ bool p3IdService::pgphash_process()
|
||||
|
||||
ssdata.pgp.lastCheckTs = time(NULL);
|
||||
ssdata.pgp.checkAttempts++;
|
||||
ssdata.pgp.pgpId = pgpId; // read from the signature, but not verified
|
||||
}
|
||||
|
||||
if(!error)
|
||||
{
|
||||
// update IdScore too.
|
||||
ssdata.score.rep.updateIdScore(true, ssdata.pgp.idKnown);
|
||||
ssdata.score.rep.updateIdScore(true, ssdata.pgp.validatedSignature);
|
||||
ssdata.score.rep.update();
|
||||
|
||||
/* set new Group ServiceString */
|
||||
@ -2982,6 +3000,24 @@ bool p3IdService::checkId(const RsGxsIdGroup &grp, RsPgpId &pgpId,bool& error)
|
||||
/* iterate through and check hash */
|
||||
Sha1CheckSum ans = grp.mPgpIdHash;
|
||||
|
||||
#ifdef DEBUG_IDS
|
||||
std::string esign ;
|
||||
Radix64::encode((char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),esign) ;
|
||||
std::cerr << "Checking group signature " << esign << std::endl;
|
||||
#endif
|
||||
RsPgpId issuer_id ;
|
||||
|
||||
if(mPgpUtils->parseSignature((unsigned char *) grp.mPgpIdSign.c_str(), grp.mPgpIdSign.length(),issuer_id))
|
||||
{
|
||||
std::cerr << "Issuer found: " << issuer_id << std::endl;
|
||||
pgpId = issuer_id ;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Signature parsing failed!!" << std::endl;
|
||||
pgpId.clear() ;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_IDS
|
||||
std::cerr << "\tExpected Answer: " << ans.toStdString();
|
||||
std::cerr << std::endl;
|
||||
@ -2995,6 +3031,7 @@ bool p3IdService::checkId(const RsGxsIdGroup &grp, RsPgpId &pgpId,bool& error)
|
||||
Sha1CheckSum hash;
|
||||
calcPGPHash(RsGxsId(grp.mMeta.mGroupId), mit->second, hash);
|
||||
|
||||
|
||||
if (ans == hash)
|
||||
{
|
||||
#ifdef DEBUG_IDS
|
||||
@ -3342,7 +3379,7 @@ bool p3IdService::recogn_process()
|
||||
|
||||
// update IdScore too.
|
||||
bool pgpId = (item->meta.mGroupFlags & RSGXSID_GROUPFLAG_REALID);
|
||||
ssdata.score.rep.updateIdScore(pgpId, ssdata.pgp.idKnown);
|
||||
ssdata.score.rep.updateIdScore(pgpId, ssdata.pgp.validatedSignature);
|
||||
ssdata.score.rep.update();
|
||||
|
||||
/* set new Group ServiceString */
|
||||
|
@ -100,12 +100,12 @@ class SSGxsIdPgp: public SSBit
|
||||
{
|
||||
public:
|
||||
SSGxsIdPgp()
|
||||
:idKnown(false), lastCheckTs(0), checkAttempts(0) { return; }
|
||||
:validatedSignature(false), lastCheckTs(0), checkAttempts(0) { return; }
|
||||
|
||||
virtual bool load(const std::string &input);
|
||||
virtual std::string save() const;
|
||||
|
||||
bool idKnown;
|
||||
bool validatedSignature;
|
||||
time_t lastCheckTs;
|
||||
uint32_t checkAttempts;
|
||||
RsPgpId pgpId;
|
||||
|
@ -903,10 +903,11 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item,
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setText(RSID_COL_IDTYPE, tr("Unknown PGP key"));
|
||||
item->setToolTip(RSID_COL_IDTYPE,tr("Unknown key ID")) ;
|
||||
item->setToolTip(RSID_COL_KEYID,tr("Unknown key ID")) ;
|
||||
QString txt = tr("[Unknown node]");
|
||||
item->setText(RSID_COL_IDTYPE, txt);
|
||||
item->setToolTip(RSID_COL_IDTYPE,tr("Unverified signature from ")+QString::fromStdString(data.mPgpId.toStdString())) ;
|
||||
|
||||
item->setToolTip(RSID_COL_KEYID,tr("Unverified signature from ")+QString::fromStdString(data.mPgpId.toStdString())) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1081,7 +1082,10 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
ui->lineEdit_Nickname->setText(QString::fromUtf8(data.mMeta.mGroupName.c_str()).left(RSID_MAXIMUM_NICKNAME_SIZE));
|
||||
ui->lineEdit_KeyId->setText(QString::fromStdString(data.mMeta.mGroupId.toStdString()));
|
||||
//ui->lineEdit_GpgHash->setText(QString::fromStdString(data.mPgpIdHash.toStdString()));
|
||||
ui->lineEdit_GpgId->setText(QString::fromStdString(data.mPgpId.toStdString()));
|
||||
if(data.mPgpKnown)
|
||||
ui->lineEdit_GpgId->setText(QString::fromStdString(data.mPgpId.toStdString()));
|
||||
else
|
||||
ui->lineEdit_GpgId->setText(QString::fromStdString(data.mPgpId.toStdString()) + tr(" [unverified]"));
|
||||
|
||||
time_t now = time(NULL) ;
|
||||
ui->lineEdit_LastUsed->setText(getHumanReadableDuration(now - data.mLastUsageTS)) ;
|
||||
@ -1109,30 +1113,33 @@ void IdDialog::insertIdDetails(uint32_t token)
|
||||
else
|
||||
{
|
||||
if (data.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID)
|
||||
{
|
||||
ui->lineEdit_GpgName->setText(tr("Unknown real name"));
|
||||
}
|
||||
ui->lineEdit_GpgName->setText(tr("[Unknown node]"));
|
||||
else
|
||||
{
|
||||
ui->lineEdit_GpgName->setText(tr("Anonymous Id"));
|
||||
}
|
||||
}
|
||||
|
||||
if(data.mPgpId.isNull())
|
||||
{
|
||||
ui->lineEdit_GpgId->hide() ;
|
||||
ui->lineEdit_GpgName->hide() ;
|
||||
ui->PgpId_LB->hide() ;
|
||||
ui->PgpName_LB->hide() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->lineEdit_GpgId->show() ;
|
||||
ui->lineEdit_GpgName->show() ;
|
||||
ui->PgpId_LB->show() ;
|
||||
ui->PgpName_LB->show() ;
|
||||
}
|
||||
|
||||
if(data.mPgpKnown)
|
||||
{
|
||||
ui->lineEdit_GpgName->show() ;
|
||||
ui->PgpName_LB->show() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->lineEdit_GpgName->hide() ;
|
||||
ui->PgpName_LB->hide() ;
|
||||
}
|
||||
|
||||
bool isLinkedToOwnPgpId = (data.mPgpKnown && (data.mPgpId == ownPgpId)) ;
|
||||
bool isOwnId = (data.mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user