/******************************************************************************* * libretroshare/src/pqi: authgpg.cc * * * * libretroshare: retroshare core library * * * * Copyright 2008-2009 by Robert Fernie, Retroshare Team. * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * This program 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 Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * * *******************************************************************************/ #include "authgpg.h" #include "retroshare/rsiface.h" // For rsicontrol. #include "retroshare/rspeers.h" // For RsPeerDetails. #ifdef WINDOWS_SYS #include "retroshare/rsinit.h" #endif #include "rsserver/p3face.h" #include "pqi/p3notify.h" #include "pgp/pgphandler.h" #include #include #include #include /* for (u)sleep() */ #include #include #include #include #include "rsitems/rsconfigitems.h" #define LIMIT_CERTIFICATE_SIZE 1 #define MAX_CERTIFICATE_SIZE 10000 //#define DEBUG_AUTHGPG 1 //const rstime_t STORE_KEY_TIMEOUT = 1 * 60 * 60; //store key is call around every hour AuthPGP *AuthPGP::_instance = NULL ; void cleanupZombies(int numkill); // function to cleanup zombies under OSX. //#define GPG_DEBUG 1 /* Function to sign X509_REQ via GPGme. */ int AuthPGP::availablePgpCertificatesWithPrivateKeys(std::list& pgpIds) { return instance()->mPgpHandler->availableGPGCertificatesWithPrivateKeys(pgpIds); } bool AuthPGP::getPgpDetailsFromBinaryBlock(const unsigned char *mem,size_t mem_size,RsPgpId& key_id, std::string& name, std::list& signers) { return instance()->mPgpHandler->getGPGDetailsFromBinaryBlock(mem,mem_size,key_id,name,signers); } void AuthPGP::registerToConfigMgr(const std::string& fname,p3ConfigMgr *CfgMgr) { CfgMgr->addConfiguration(fname, instance()); } bool AuthPGP::decryptTextFromFile(std::string& text,const std::string& inputfile) { return instance()->mPgpHandler->decryptTextFromFile(instance()->mOwnGpgId,text,inputfile) ; } bool AuthPGP::removeKeysFromPGPKeyring(const std::set& pgp_ids,std::string& backup_file,uint32_t& error_code) { // std::list pids ; // // for(std::list::const_iterator it(pgp_ids.begin());it!=pgp_ids.end();++it) // pids.push_back(RsPgpId(*it)) ; return instance()->mPgpHandler->removeKeysFromPGPKeyring(pgp_ids,backup_file,error_code) ; } // bool AuthGPG::decryptTextFromString(std::string& encrypted_text,std::string& output) // { // return instance()->mPgpHandler->decryptTextFromString(mOwnGpgId,encrypted_text,output) ; // } bool AuthPGP::encryptTextToFile(const std::string& text,const std::string& outfile) { return instance()->mPgpHandler->encryptTextToFile(instance()->mOwnGpgId,text,outfile) ; } // bool AuthGPG::encryptTextToString(const std::string& pgp_id,const std::string& text,std::string& outstr) // { // return instance()->mPgpHandler->encryptTextToString(RsPgpId(pgp_id),text,outstr) ; // } std::string pgp_pwd_callback(void * /*hook*/, const char *uid_title, const char *uid_hint, const char * /*passphrase_info*/, int prev_was_bad,bool *cancelled) { #ifdef GPG_DEBUG2 fprintf(stderr, "pgp_pwd_callback() called.\n"); #endif std::string password; RsServer::notify()->askForPassword(uid_title, uid_hint, prev_was_bad, password,cancelled) ; return password ; } void AuthPGP::init( const std::string& path_to_public_keyring, const std::string& path_to_secret_keyring, const std::string& path_to_trustdb, const std::string& pgp_lock_file) { if(_instance != NULL) { std::cerr << "AuthGPG::init() called twice!" << std::endl ; print_stacktrace(); return; } _instance = new AuthPGP( path_to_public_keyring, path_to_secret_keyring, path_to_trustdb, pgp_lock_file ); _instance->mPgpHandler->setPassphraseCallback(pgp_pwd_callback); } void AuthPGP::exit() { if(_instance) { _instance->fullstop(); delete _instance; _instance = nullptr; } } AuthPGP::AuthPGP(const std::string& path_to_public_keyring,const std::string& path_to_secret_keyring,const std::string& path_to_trustdb,const std::string& pgp_lock_file) :p3Config(), gpgMtxService("AuthGPG-service"), gpgMtxEngine("AuthGPG-engine"), gpgMtxData("AuthGPG-data"), mStoreKeyTime(0), gpgKeySelected(false), _force_sync_database(false), mCount(0) { mPgpHandler = new OpenPGPSDKHandler(path_to_public_keyring,path_to_secret_keyring,path_to_trustdb,pgp_lock_file); start("AuthGPG"); } /* This function is called when retroshare is first started * to get the list of available GPG certificates. * This function should only return certs for which * the private(secret) keys are available. * * returns false if GnuPG is not available. */ //bool AuthGPG::availableGPGCertificatesWithPrivateKeys(std::list &ids) //{ // std::list pids ; // // mPgpHandler->availableGPGCertificatesWithPrivateKeys(pids) ; // // for(std::list::const_iterator it(pids.begin());it!=pids.end();++it) // ids.push_back( (*it).toStdString() ) ; // // /* return false if there are no private keys */ // return !ids.empty(); //} /* You can initialise Retroshare with * (a) load existing certificate. * (b) a new certificate. * * This function must be called successfully (return == 1) * before anything else can be done. (except above fn). */ int AuthPGP::PgpInit(const RsPgpId &ownId) { #ifdef DEBUG_AUTHGPG std::cerr << "AuthGPG::GPGInit() called with own gpg id : " << ownId.toStdString() << std::endl; #endif instance()->mOwnGpgId = ownId; //force the validity of the private key. When set to unknown, it caused signature and text encryptions bugs instance()->privateTrustCertificate(ownId, 5); instance()->mPgpHandler->updateOwnSignatureFlag(ownId) ; #ifdef DEBUG_AUTHGPG std::cerr << "AuthGPG::GPGInit finished." << std::endl; #endif return 1; } AuthPGP::~AuthPGP() { } void AuthPGP::threadTick() { rstime::rs_usleep(100 * 1000); //100 msec /// every 100 milliseconds processServices(); /// every ten seconds if (++mCount >= 100 || _force_sync_database) { RsStackMutex stack(gpgMtxService); ///******* LOCKED ****** /// The call does multiple things at once: /// - checks whether the keyring has changed in memory /// - checks whether the keyring has changed on disk. /// - merges/updates according to status. /// mPgpHandler->syncDatabase() ; mCount = 0; _force_sync_database = false ; }//if (++count >= 100 || _force_sync_database) } void AuthPGP::processServices() { AuthGPGOperation *operation = NULL; AuthGPGService *service = NULL; { RsStackMutex stack(gpgMtxService); /******* LOCKED ******/ std::list::iterator serviceIt; for (serviceIt = services.begin(); serviceIt != services.end(); ++serviceIt) { operation = (*serviceIt)->getGPGOperation(); if (operation) { service = *serviceIt; break; } } } /******* UNLOCKED ******/ if (operation == NULL) { /* nothing to do */ return; } if (service == NULL) { /* huh ? */ delete operation; return; } AuthGPGOperationLoadOrSave *loadOrSave = dynamic_cast(operation); if (loadOrSave) { if (loadOrSave->m_load) { /* process load operation */ /* load the certificate */ /* don't bother loading - if we already have the certificate */ if (mPgpHandler->isGPGId(loadOrSave->m_certGpgId)) { #ifdef GPG_DEBUG std::cerr << "AuthGPGimpl::processServices() Skipping load - already have it" << std::endl; #endif } else { #ifdef GPG_DEBUG std::cerr << "AuthGPGimpl::processServices() Process load operation" << std::endl; #endif std::string error_string ; RsPgpId pgp_id ; LoadCertificateFromString(loadOrSave->m_certGpg, pgp_id,error_string); loadOrSave->m_certGpgId = pgp_id; } } else { /* process save operation */ #ifdef GPG_DEBUG std::cerr << "AuthGPGimpl::processServices() Process save operation" << std::endl; #endif /* save the certificate to string */ /***** * #define DISABLE_CERTIFICATE_SEND 1 ****/ loadOrSave->m_certGpg = SaveCertificateToString(loadOrSave->m_certGpgId,true); #ifdef GPG_DEBUG std::cerr << "Certificate for: " << loadOrSave->m_certGpgId << " is: "; std::cerr << std::endl; std::cerr << loadOrSave->m_certGpg; std::cerr << std::endl; #endif } service->setGPGOperation(loadOrSave); } else { #ifdef GPG_DEBUG std::cerr << "AuthGPGimpl::processServices() Unknown operation" << std::endl; #endif } delete operation; } bool AuthPGP::DoOwnSignature(const void *data, unsigned int datalen, void *buf_sigout, unsigned int *outl, std::string reason /* = "" */) { return instance()->mPgpHandler->SignDataBin(mOwnGpgId,data,datalen,(unsigned char *)buf_sigout,outl,false,reason) ; } /* import to GnuPG and other Certificates */ bool AuthPGP::VerifySignature(const void *data, int datalen, const void *sig, unsigned int siglen, const PGPFingerprintType& withfingerprint) { return instance()->mPgpHandler->VerifySignBin((unsigned char*)data,datalen,(unsigned char*)sig,siglen,withfingerprint) ; } bool AuthPGP::parseSignature(const void *sig, unsigned int siglen, RsPgpId& issuer_id) { return instance()->mPgpHandler->parseSignature((unsigned char*)sig,siglen,issuer_id) ; } bool AuthPGP::exportProfile(const std::string& fname,const RsPgpId& exported_id) { return instance()->mPgpHandler->exportGPGKeyPair(fname,exported_id) ; } bool AuthPGP::exportIdentityToString( std::string& data, const RsPgpId& pgpId, bool includeSignatures, std::string& errorMsg ) { return instance()->mPgpHandler->exportGPGKeyPairToString( data, pgpId, includeSignatures, errorMsg); } bool AuthPGP::importProfile(const std::string& fname,RsPgpId& imported_id,std::string& import_error) { return instance()->mPgpHandler->importGPGKeyPair(fname,imported_id,import_error) ; } bool AuthPGP::importProfileFromString(const std::string &data, RsPgpId &gpg_id, std::string &import_error) { return instance()->mPgpHandler->importGPGKeyPairFromString(data, gpg_id, import_error); } bool AuthPGP::active() { RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ return instance()->gpgKeySelected; } bool AuthPGP::GeneratePgpCertificate(const std::string& name, const std::string& email, const std::string& passwd, RsPgpId& pgpId, const int keynumbits, std::string& errString) { RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/ return instance()->mPgpHandler->GeneratePGPCertificate(name, email, passwd, pgpId, keynumbits, errString) ; } /**** These Two are common */ std::string AuthPGP::getPgpName(const RsPgpId& id,bool *success) { RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ const PGPCertificateInfo *info = instance()->mPgpHandler->getCertificateInfo(id) ; if(info != NULL) { if(success != NULL) *success = true ; return info->_name ; } else { if(success != NULL) *success = false ; return "[Unknown PGP Cert name]" ; } } AuthPGP *AuthPGP::instance() { if(!_instance) { RS_ERR("called before AuthGPG::init()"); print_stacktrace(); return nullptr; } return _instance; } bool AuthPGP::isPGPId(const RsPgpId& id) { return instance()->mPgpHandler->isGPGId(id); } /**** These Two are common */ std::string AuthPGP::getPgpEmail(const RsPgpId& id,bool *success) { RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ const PGPCertificateInfo *info = instance()->mPgpHandler->getCertificateInfo(id) ; if(info != NULL) { if(success != NULL) *success = true ; return info->_email ; } else { if(success != NULL) *success = false ; return "[Unknown PGP Cert email]" ; } } /**** GPG versions ***/ const RsPgpId& AuthPGP::getPgpOwnId() { RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ return instance()->mOwnGpgId ; } std::string AuthPGP::getPgpOwnName() { return getPgpName(instance()->mOwnGpgId) ; } bool AuthPGP::getPgpAllList(std::list &ids) { RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ instance()->mPgpHandler->getGPGFilteredList(ids) ; return true; } const PGPCertificateInfo *AuthPGP::getCertInfoFromStdString(const std::string& pgp_id) const { try { return instance()->mPgpHandler->getCertificateInfo(RsPgpId(pgp_id)) ; } catch(std::exception& e) { std::cerr << "(EE) exception raised while constructing a PGP certificate from id \"" << pgp_id << "\": " << e.what() << std::endl; return NULL ; } } bool AuthPGP::haveSecretKey(const RsPgpId& id) { return instance()->mPgpHandler->haveSecretKey(id) ; } bool AuthPGP::isKeySupported(const RsPgpId& id) { const PGPCertificateInfo *pc = instance()->mPgpHandler->getCertificateInfo(id) ; if(pc == NULL) return false ; return !(pc->_flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM) ; } bool AuthPGP::getPgpDetails(const RsPgpId& pgp_id, RsPeerDetails &d) { RsStackMutex stack(instance()->gpgMtxData); /******* LOCKED ******/ const PGPCertificateInfo *pc = instance()->mPgpHandler->getCertificateInfo(pgp_id) ; if(pc == NULL) return false ; const PGPCertificateInfo& cert(*pc) ; d.id.clear() ; d.gpg_id = pgp_id ; d.name = cert._name; d.lastUsed = cert._time_stamp; d.email = cert._email; d.trustLvl = cert._trustLvl; d.validLvl = cert._trustLvl; d.ownsign = cert._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE; d.gpgSigners.clear() ; for(std::set::const_iterator it(cert.signers.begin());it!=cert.signers.end();++it) d.gpgSigners.push_back( *it ) ; d.fpr = cert._fpr ; d.accept_connection = cert._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION; d.hasSignedMe = cert._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME; return true; } bool AuthPGP::getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&)) { return instance()->mPgpHandler->getGPGFilteredList(list,filter) ; } static bool filter_Validity(const PGPCertificateInfo& /*info*/) { return true ; } //{ return info._validLvl >= PGPCertificateInfo::GPGME_VALIDITY_MARGINAL ; } static bool filter_Accepted(const PGPCertificateInfo& info) { return info._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_ACCEPT_CONNEXION ; } static bool filter_OwnSigned(const PGPCertificateInfo& info) { return info._flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE ; } bool AuthPGP::getPgpValidList(std::list &ids) { return getGPGFilteredList(ids,&filter_Validity); } bool AuthPGP::getPgpAcceptedList(std::list &ids) { return getGPGFilteredList(ids,&filter_Accepted); } bool AuthPGP::getPgpSignedList(std::list &ids) { return getGPGFilteredList(ids,&filter_OwnSigned); } // bool AuthGPG::getCachedGPGCertificate(const RsPgpId &id, std::string &certificate) // { // RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ // #ifdef LIMIT_CERTIFICATE_SIZE // certificate = instance()->mPgpHandler->SaveCertificateToString(RsPgpId(id),false) ; // #else // certificate = instance()->mPgpHandler->SaveCertificateToString(RsPgpId(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 ; // } /***************************************************************** * Loading and Saving Certificates - this has to * be able to handle both openpgp and X509 certificates. * * X509 are passed onto AuthSSL, OpenPGP are passed to gpgme. * */ /* SKTAN : do not know how to use std::string id */ std::string AuthPGP::SaveCertificateToString(const RsPgpId &id,bool include_signatures) { RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/ return instance()->mPgpHandler->SaveCertificateToString(id,include_signatures) ; } /* import to GnuPG and other Certificates */ bool AuthPGP::LoadPGPKeyFromBinaryData(const unsigned char *data,uint32_t data_len, RsPgpId& gpg_id,std::string& error_string) { RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/ if(instance()->mPgpHandler->LoadCertificateFromBinaryData(data,data_len,gpg_id,error_string)) { instance()->mPgpHandler->updateOwnSignatureFlag(gpg_id,instance()->mOwnGpgId) ; return true ; } return false ; } /* import to GnuPG and other Certificates */ bool AuthPGP::LoadCertificateFromString(const std::string &str, RsPgpId& gpg_id,std::string& error_string) { RsStackMutex stack(instance()->gpgMtxEngine); /******* LOCKED ******/ if(instance()->mPgpHandler->LoadCertificateFromString(str,gpg_id,error_string)) { instance()->mPgpHandler->updateOwnSignatureFlag(gpg_id,instance()->mOwnGpgId) ; return true ; } return false ; } /***************************************************************** * Auth...? Signing, Revoke, Trust are all done at * the PGP level.... * * Only Signing of SSL is done at setup. * Auth should be done... ?? not sure * maybe * */ /*************************************/ /* These take PGP Ids */ bool AuthPGP::AllowConnection(const RsPgpId& gpg_id, bool accept) { #ifdef GPG_DEBUG std::cerr << "AuthGPG::AllowConnection(" << gpg_id << ")" << std::endl; #endif /* Was a "Reload Certificates" here -> be shouldn't be needed -> and very expensive, try without. */ { RsStackMutex stack(instance()->gpgMtxData); instance()->mPgpHandler->setAcceptConnexion(gpg_id,accept) ; } instance()->IndicateConfigChanged(RsConfigMgr::CheckPriority::SAVE_NOW); RsServer::notify()->notifyListChange(NOTIFY_LIST_FRIENDS, accept ? NOTIFY_TYPE_ADD : NOTIFY_TYPE_DEL); return true; } /* These take PGP Ids */ bool AuthPGP::SignCertificateLevel0(const RsPgpId &id) { #ifdef GPG_DEBUG std::cerr << "AuthGPG::SignCertificat(" << id << ")" << std::endl; #endif return instance()->privateSignCertificate(id) ; } bool AuthPGP::RevokeCertificate(const RsPgpId &id) { /* remove unused parameter warnings */ (void) id; #ifdef GPG_DEBUG std::cerr << "AuthGPG::RevokeCertificate(" << id << ") not implemented yet" << std::endl; #endif return false; } bool AuthPGP::TrustCertificate(const RsPgpId& id, int trustlvl) { #ifdef GPG_DEBUG std::cerr << "AuthGPG::TrustCertificate(" << id << ", " << trustlvl << ")" << std::endl; #endif return instance()->privateTrustCertificate(id, trustlvl) ; } bool AuthPGP::encryptDataBin(const RsPgpId& pgp_id,const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) { return instance()->mPgpHandler->encryptDataBin(RsPgpId(pgp_id),data,datalen,sign,signlen) ; } bool AuthPGP::decryptDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) { return instance()->mPgpHandler->decryptDataBin(instance()->mOwnGpgId,data,datalen,sign,signlen) ; } bool AuthPGP::SignDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen, std::string reason /*= ""*/) { return instance()->DoOwnSignature(data, datalen, sign, signlen, reason); } bool AuthPGP::exportPublicKey( const RsPgpId& id, unsigned char*& mem_block, size_t& mem_size, bool armoured, bool include_signatures ) { return instance()->mPgpHandler->exportPublicKey(id,mem_block,mem_size,armoured,include_signatures); } bool AuthPGP::isPgpPubKeyAvailable(const RsPgpId& pgp_id) { return instance()->mPgpHandler->isPgpPubKeyAvailable(pgp_id); } bool AuthPGP::getKeyFingerprint(const RsPgpId& id,PGPFingerprintType& fp) { return instance()->mPgpHandler->getKeyFingerprint(id,fp); } bool AuthPGP::VerifySignBin(const void *data, uint32_t datalen, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint) { return instance()->VerifySignature(data, datalen, sign, signlen, withfingerprint); } /* Sign/Trust stuff */ int AuthPGP::privateSignCertificate(const RsPgpId &id) { RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ int ret = mPgpHandler->privateSignCertificate(mOwnGpgId,id) ; _force_sync_database = true ; return ret ; } /* revoke the signature on Certificate */ int AuthPGP::privateRevokeCertificate(const RsPgpId &/*id*/) { //RsStackMutex stack(gpgMtx); /******* LOCKED ******/ std::cerr << __PRETTY_FUNCTION__ << ": not implemented!" << std::endl; return 0; } int AuthPGP::privateTrustCertificate(const RsPgpId& id, int trustlvl) { RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ // csoler: Why are we not allowing this when the peer is not in the accepted peers list?? // The trust level is only a user-defined property that has nothing to // do with the fact that we allow connections or not. if(!isPGPAccepted(id)) return 0; int res = instance()->mPgpHandler->privateTrustCertificate(id,trustlvl) ; _force_sync_database = true ; return res ; } // -----------------------------------------------------------------------------------// // -------------------------------- Config functions ------------------------------ // // -----------------------------------------------------------------------------------// // RsSerialiser *AuthPGP::setupSerialiser() { RsSerialiser *rss = new RsSerialiser ; rss->addSerialType(new RsGeneralConfigSerialiser()); return rss ; } bool AuthPGP::isPGPAccepted(const RsPgpId& id) { return instance()->mPgpHandler->isGPGAccepted(id); } bool AuthPGP::saveList(bool& cleanup, std::list& lst) { #ifdef GPG_DEBUG std::cerr << "AuthGPG::saveList() called" << std::endl ; #endif std::list ids ; getPgpAcceptedList(ids) ; // needs to be done before the lock RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ cleanup = true ; // Now save config for network digging strategies RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; for (std::list::const_iterator it(ids.begin()); it != ids.end(); ++it) if((*it) != mOwnGpgId) // skip our own id. { RsTlvKeyValue kv; kv.key = (*it).toStdString() ; #ifdef GPG_DEBUG std::cerr << "AuthGPG::saveList() called (it->second) : " << (it->second) << std::endl ; #endif kv.value = "TRUE"; vitem->tlvkvs.pairs.push_back(kv) ; } lst.push_back(vitem); return true; } bool AuthPGP::loadList(std::list& load) { #ifdef GPG_DEBUG std::cerr << "AuthGPG::loadList() Item Count: " << load.size() << std::endl; #endif RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ /* load the list of accepted gpg keys */ std::list::iterator it; for(it = load.begin(); it != load.end(); ++it) { RsConfigKeyValueSet *vitem = dynamic_cast(*it); if(vitem) { #ifdef GPG_DEBUG std::cerr << "AuthGPG::loadList() General Variable Config Item:" << std::endl; vitem->print(std::cerr, 10); std::cerr << std::endl; #endif std::list::iterator kit; for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) if (kit->key != mOwnGpgId.toStdString()) instance()->mPgpHandler->setAcceptConnexion(RsPgpId(kit->key), (kit->value == "TRUE")); } delete (*it); } load.clear() ; return true; } bool AuthPGP::addService(AuthGPGService *service) { RsStackMutex stack(instance()->gpgMtxService); /********* LOCKED *********/ if (std::find(instance()->services.begin(), instance()->services.end(), service) != instance()->services.end()) { /* it exists already! */ return false; } instance()->services.push_back(service); return true; }