- Fixed deadlock when asking for GPG passwd with gpg callback during session.

- Added a method lockAllEvents()/unlockAllEvents() to remove timer updates in RsAutoUpdatePage
- Updated passwd message to be more user-friendly
- removed some warnings in authgpg.cc

- Trunk to branch portage:

  2703: added commandline option '-U' to allow user to access different profile 
         - in the situation where autologin is enabled 
         - BUG found (or rather autologin induced it), if one asks to make friends to a 
  	     peer (in ConfCertDialg) 'within' a session that uses autologin it freezes 
  
  2697: add the internal counter mutex lock. Move the code of the rw mutec to the rsthreads.cc file
  2696: fix a code bug
  2695: add a read / write lock and refactor authgpg with it
  2694: Add own key to p3disc clients


WARNING: this commit needs a clean compilation




git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5.0@2732 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
csoler 2010-04-19 20:17:33 +00:00
parent 9eccfef9c1
commit 97359c93f9
15 changed files with 508 additions and 365 deletions

View File

@ -71,38 +71,20 @@ gpgcert::~gpgcert()
}
}
static std::string gpg_password_static;
static bool is_set_gpg_password_static = false;
#define GPG_DEBUG2
gpg_error_t pgp_pwd_callback(void *hook, const char *uid_hint, const char *passphrase_info, int prev_was_bad, int fd)
{
#ifdef GPG_DEBUG
#ifdef GPG_DEBUG2
fprintf(stderr, "pgp_pwd_callback() called.\n");
#endif
#endif
std::string text = rsicontrol->getNotify().askForPassword(uid_hint,prev_was_bad);
std::string text;
if (is_set_gpg_password_static) {
#ifdef GPG_DEBUG
fprintf(stderr, "pgp_pwd_callback() using already setted password.\n");
#endif
text = gpg_password_static;
} else {
if(prev_was_bad || !AuthGPG::getAuthGPG()->getAutorisePasswordCallbackNotify()) {
#ifdef GPG_DEBUG
fprintf(stderr, "pgp_pwd_callback() allow only one try to be consistent with gpg agent.\n");
#endif
text = "";
} else {
text = rsicontrol->getNotify().askForPassword(uid_hint);
#ifdef GPG_DEBUG
#ifdef GPG_DEBUG2
std::cerr << "pgp_pwd_callback() got GPG passwd from gui." << std::endl;
#endif
gpg_password_static = text;
is_set_gpg_password_static = true;
}
}
#endif
if((void*)fd != NULL)
{
#ifndef WINDOWS_SYS
write(fd, text.c_str(), text.size());
write(fd, "\n", 1); /* needs a new line? */
@ -112,21 +94,20 @@ gpg_error_t pgp_pwd_callback(void *hook, const char *uid_hint, const char *passp
WriteFile(winFd, text.c_str(), text.size(), &written, NULL);
WriteFile(winFd, "\n", 1, &written, NULL);
#endif
}
#ifdef GPG_DEBUG
#ifdef GPG_DEBUG2
fprintf(stderr, "pgp_pwd_callback() password setted\n");
#endif
#endif
return 0;
}
static char *PgpPassword = NULL;
AuthGPG::AuthGPG()
:gpgmeInit(false),gpgmeKeySelected(false),autorisePasswordCallbackNotify(true),p3Config(CONFIG_TYPE_AUTHGPG)
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
{
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
setlocale(LC_ALL, "");
gpgme_check_version(NULL);
@ -138,11 +119,11 @@ AuthGPG::AuthGPG()
#ifndef WINDOWS_SYS
/* setup the engine (gpg2) */
// if (GPG_ERR_NO_ERROR != gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, "/usr/bin/gpg2", NULL))
// {
// std::cerr << "Error creating Setting engine" << std::endl;
// return;
// }
// if (GPG_ERR_NO_ERROR != gpgme_set_engine_info(GPGME_PROTOCOL_OpenPGP, "/usr/bin/gpg2", NULL))
// {
// std::cerr << "Error creating Setting engine" << std::endl;
// return;
// }
#endif
if (GPG_ERR_NO_ERROR != gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP))
@ -190,8 +171,8 @@ AuthGPG::AuthGPG()
gpgme_set_passphrase_cb(CTX, pgp_pwd_callback, (void *) NULL);
/* if we get to here -> we have inited okay */
gpgmeInit = true;
}
storeAllKeys_locked();
#ifdef GPG_DEBUG
@ -209,13 +190,13 @@ AuthGPG::AuthGPG()
*/
bool AuthGPG::availableGPGCertificatesWithPrivateKeys(std::list<std::string> &ids)
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
int i = 0;
gpgme_key_t KEY = NULL;
gpg_error_t ERR;
/* XXX should check that CTX is valid */
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
if (!gpgmeInit)
{
return false;
@ -269,36 +250,43 @@ bool AuthGPG::availableGPGCertificatesWithPrivateKeys(std::list<std::string> &id
*/
int AuthGPG::GPGInit(std::string ownId)
{
is_set_gpg_password_static= false;
std::cerr << "AuthGPG::GPGInit() called with own gpg id : " << ownId << std::endl;
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
std::cerr << "AuthGPG::GPGInit() called with own gpg id : " << ownId << std::endl;
is_set_gpg_password_static= false;
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
if (!gpgmeInit) {
return 0;
}
mOwnGpgId = ownId;
}
storeAllKeys_locked();
int lvl = 0;
{
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
if (mOwnGpgCert.id != mOwnGpgId) {
std::cerr << "AuthGPG::GPGInit() failed to find your id." << std::endl;
return 0;
}
gpgmeKeySelected = true;
lvl = mOwnGpgCert.validLvl;
}
//check the validity of the private key. When set to unknown, it caused signature and text encryptions bugs
if (mOwnGpgCert.validLvl < 2) {
if (lvl < 2) {
std::cerr << "AuthGPG::GPGInit() abnormal validity set to private key. Switch it to none by default." << std::endl;
privateTrustCertificate(mOwnGpgId, 4);
}
gpgmeKeySelected = true;
//printAllKeys_locked();
std::cerr << "AuthGPG::GPGInit finished." << std::endl;
return true;
@ -313,7 +301,6 @@ bool AuthGPG::storeAllKeys_timed() {
std::cerr << "AuthGPG::storeAllKeys_timed() called." << std::endl;
#endif
if ((time(NULL) - mStoreKeyTime) > STORE_KEY_TIMEOUT) {
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
storeAllKeys_locked();
}
return true ;
@ -325,7 +312,8 @@ bool AuthGPG::storeAllKeys_locked()
#ifdef GPG_DEBUG
std::cerr << "AuthGPG::storeAllKeys_locked()" << std::endl;
#endif
mStoreKeyTime = time(NULL);
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
gpg_error_t ERR;
if (!gpgmeInit)
@ -359,6 +347,7 @@ bool AuthGPG::storeAllKeys_locked()
}
/* Loop until end of key */
mStoreKeyTime = time(NULL);
ERR = gpgme_op_keylist_next (CTX, &KEY);
if (GPG_ERR_NO_ERROR != ERR) {
std::cerr << "AuthGPG::storeAllKeys_locked() didn't find any gpg key in the keyring" << std::endl;
@ -408,7 +397,6 @@ bool AuthGPG::storeAllKeys_locked()
/* NB uids is a linked list and can contain multiple ids.
* first id is primary.
*/
gpgme_user_id_t mainuid = KEY->uids;
nu.name = mainuid->name;
nu.email = mainuid->email;
@ -503,7 +491,7 @@ bool AuthGPG::storeAllKeys_locked()
}
// update trust on all available keys.
// update trust on all available keys. Not used anymore
bool AuthGPG::updateTrustAllKeys_locked()
{
gpg_error_t ERR;
@ -515,7 +503,6 @@ bool AuthGPG::updateTrustAllKeys_locked()
/* have to do this the hard way! */
gpgme_trust_item_t ti = NULL;
std::map<std::string, gpgcert>::iterator it;
for(it = mKeyList.begin(); it != mKeyList.end(); it++)
@ -537,6 +524,8 @@ bool AuthGPG::updateTrustAllKeys_locked()
/* Loop until end of key */
#ifdef GPG_DEBUG
gpgme_trust_item_t ti = NULL;
for(int i = 0;(GPG_ERR_NO_ERROR == (ERR = gpgme_op_trustlist_next (CTX, &ti))); i++)
{
std::string keyid = ti->keyid;
@ -624,7 +613,7 @@ bool AuthGPG::printOwnKeys_locked()
bool AuthGPG::printKeys()
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
printAllKeys_locked();
return printOwnKeys_locked();
}
@ -672,6 +661,7 @@ void print_pgpme_verify_summary(unsigned int summary)
bool AuthGPG::DoOwnSignature_locked(const void *data, unsigned int datalen, void *buf_sigout, unsigned int *outl)
{
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
/* setup signers */
gpgme_signers_clear(CTX);
if (GPG_ERR_NO_ERROR != gpgme_signers_add(CTX, mOwnGpgCert.key))
@ -733,7 +723,6 @@ bool AuthGPG::DoOwnSignature_locked(const void *data, unsigned int datalen, void
/* now extract the data from gpgmeSig */
size_t len = 0;
int len2 = len;
// gpgme_data_write (gpgmeSig, "", 1); // to be able to convert it into a string
char *export_sig = gpgme_data_release_and_get_mem(gpgmeSig, &len);
#ifdef GPG_DEBUG
@ -764,6 +753,7 @@ bool AuthGPG::VerifySignature_locked(const void *data, int datalen, const void *
std::cerr << "VerifySignature: datalen: " << datalen << " siglen: " << siglen << std::endl;
#endif
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
if(!(gpgmeInit || gpgmeKeySelected))
return false ;
@ -847,7 +837,6 @@ bool AuthGPG::VerifySignature_locked(const void *data, int datalen, const void *
fprintf(stderr, "AuthGPG::VerifySignature() FAILED\n");
}
return valid;
}
@ -856,12 +845,15 @@ bool AuthGPG::VerifySignature_locked(const void *data, int datalen, const void *
bool AuthGPG::active()
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
return ((gpgmeInit) && (gpgmeKeySelected));
}
bool AuthGPG::GeneratePGPCertificate(std::string name, std::string email, std::string passwd, std::string &pgpId, std::string &errString) {
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
gpgme_key_t newKey;
gpgme_genkey_result_t result;
gpg_error_t ERR;
@ -895,7 +887,8 @@ bool AuthGPG::CloseAuth()
std::string AuthGPG::getGPGName(GPG_id id)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
certmap::iterator it;
if (mKeyList.end() != (it = mKeyList.find(id)))
@ -908,7 +901,8 @@ std::string AuthGPG::getGPGName(GPG_id id)
std::string AuthGPG::getGPGEmail(GPG_id id)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
certmap::iterator it;
if (mKeyList.end() != (it = mKeyList.find(id)))
@ -921,20 +915,20 @@ std::string AuthGPG::getGPGEmail(GPG_id id)
std::string AuthGPG::getGPGOwnId()
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
return mOwnGpgId;
}
std::string AuthGPG::getGPGOwnName()
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
return mOwnGpgCert.name;
}
bool AuthGPG::getGPGAllList(std::list<std::string> &ids)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
/* add an id for each pgp certificate */
certmap::iterator it;
@ -952,7 +946,7 @@ bool AuthGPG::getGPGDetails(std::string id, RsPeerDetails &d)
#endif
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
/* add an id for each pgp certificate */
certmap::iterator it;
@ -989,7 +983,7 @@ bool AuthGPG::getGPGDetails(std::string id, RsPeerDetails &d)
}
bool AuthGPG::decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN) {
//RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
gpgme_set_armor (CTX, 1);
gpg_error_t ERR;
if (GPG_ERR_NO_ERROR != (ERR = gpgme_op_decrypt (CTX, CIPHER, PLAIN)))
@ -1003,7 +997,7 @@ bool AuthGPG::decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN) {
}
bool AuthGPG::encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER) {
//RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
gpgme_encrypt_flags_t* flags = new gpgme_encrypt_flags_t();
gpgme_key_t keys[2] = {mOwnGpgCert.key, NULL};
gpgme_set_armor (CTX, 1);
@ -1021,7 +1015,7 @@ bool AuthGPG::encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER) {
bool AuthGPG::getGPGValidList(std::list<std::string> &ids)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
/* add an id for each pgp certificate */
certmap::iterator it;
for(it = mKeyList.begin(); it != mKeyList.end(); it++)
@ -1036,7 +1030,7 @@ bool AuthGPG::getGPGValidList(std::list<std::string> &ids)
bool AuthGPG::getGPGAcceptedList(std::list<std::string> &ids)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
certmap::iterator it;
for(it = mKeyList.begin(); it != mKeyList.end(); it++)
{
@ -1051,7 +1045,7 @@ bool AuthGPG::getGPGAcceptedList(std::list<std::string> &ids)
bool AuthGPG::getGPGSignedList(std::list<std::string> &ids)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
certmap::iterator it;
for(it = mKeyList.begin(); it != mKeyList.end(); it++)
{
@ -1066,7 +1060,7 @@ bool AuthGPG::getGPGSignedList(std::list<std::string> &ids)
bool AuthGPG::isGPGValid(GPG_id id)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
certmap::iterator it;
if (mKeyList.end() != (it = mKeyList.find(id))) {
return (it->second.validLvl >= GPGME_VALIDITY_MARGINAL);
@ -1079,7 +1073,7 @@ bool AuthGPG::isGPGValid(GPG_id id)
bool AuthGPG::isGPGId(GPG_id id)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
certmap::iterator it;
if (mKeyList.end() != (it = mKeyList.find(id))) {
return true;
@ -1092,7 +1086,7 @@ bool AuthGPG::isGPGId(GPG_id id)
bool AuthGPG::isGPGSigned(GPG_id id)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
certmap::iterator it;
if (mKeyList.end() != (it = mKeyList.find(id)))
{
@ -1104,7 +1098,7 @@ bool AuthGPG::isGPGSigned(GPG_id id)
bool AuthGPG::isGPGAccepted(GPG_id id)
{
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
certmap::iterator it;
if (mKeyList.end() != (it = mKeyList.find(id)))
{
@ -1132,7 +1126,7 @@ std::string AuthGPG::SaveCertificateToString(std::string id)
}
storeAllKeys_timed();
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
std::string tmp;
const char *pattern[] = { NULL, NULL };
@ -1176,16 +1170,17 @@ std::string AuthGPG::SaveCertificateToString(std::string id)
/* import to GnuPG and other Certificates */
bool AuthGPG::LoadCertificateFromString(std::string str, std::string &gpg_id)
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
if (str == "") {
#ifdef GPG_DEBUG
std::cerr << "AuthGPG::LoadCertificateFromString() cert is empty string, returning false." << std::endl;
#endif
return false;
}
int imported = 0;
std::string fingerprint;
{
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
//std::string cleancert = cleanUpCertificate(str); disable for p3disc message on windows system. Move the clean cert in p3peers
std::string cleancert = str;
@ -1203,7 +1198,6 @@ bool AuthGPG::LoadCertificateFromString(std::string str, std::string &gpg_id)
/* move string data to gpgmeData */
gpgme_set_armor (CTX, 1);
if (GPG_ERR_NO_ERROR != gpgme_op_import (CTX,gpgmeData))
{
std::cerr << "AuthGPG::LoadCertificateFromString() Error Importing Certificate" << std::endl;
@ -1213,23 +1207,24 @@ bool AuthGPG::LoadCertificateFromString(std::string str, std::string &gpg_id)
gpgme_import_result_t res = gpgme_op_import_result(CTX);
if(res->imports == NULL)
if(res == NULL || res->imports == NULL)
return false ;
std::string fingerprint = std::string(res->imports->fpr);
#ifdef GPG_DEBUG
#ifdef GPG_DEBUG
std::cerr << "AuthGPG::LoadCertificateFromString() Importing considered folowing fpr : " << fingerprint << std::endl;
#endif
#endif
int imported = res->imported;
imported = res->imported;
#ifdef GPG_DEBUG
#ifdef GPG_DEBUG
fprintf(stderr, "ImportCertificate(Considered: %d Imported: %d)\n",
res->considered, res->imported);
#endif
#endif
/* do we need to delete res??? */
gpgme_data_release (gpgmeData);
}
/* extract id(s)! (only if we actually imported one) */
if (imported) {
@ -1237,6 +1232,7 @@ bool AuthGPG::LoadCertificateFromString(std::string str, std::string &gpg_id)
}
//retrieve the id of the key
certmap::iterator it;
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
for(it = mKeyList.begin(); it != mKeyList.end(); it++)
{
if (it->second.fpr == fingerprint)
@ -1276,10 +1272,9 @@ bool AuthGPG::setAcceptToConnectGPGCertificate(std::string gpg_id, bool acceptan
std::cerr << "AuthGPG::markGPGCertificateAsFriends(" << gpg_id << ")" << std::endl;
#endif
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
/* reload stuff now ... */
storeAllKeys_locked();
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
certmap::iterator it;
if (mKeyList.end() == (it = mKeyList.find(gpg_id))) {
return false;
@ -1300,22 +1295,20 @@ bool AuthGPG::SignCertificateLevel0(GPG_id id)
std::cerr << "AuthGPG::SignCertificat(" << id << ")" << std::endl;
#endif
if (1 != privateSignCertificate(id))
{
storeAllKeys_locked();
return false;
}
/* reload stuff now ... */
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
storeAllKeys_locked();
return true;
}
bool AuthGPG::RevokeCertificate(std::string id)
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
//RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
#ifdef GPG_DEBUG
std::cerr << "AuthGPG::RevokeCertificate(" << id << ") not implemented yet" << std::endl;
@ -1329,7 +1322,15 @@ bool AuthGPG::TrustCertificate(std::string id, int trustlvl)
#ifdef GPG_DEBUG
std::cerr << "AuthGPG::TrustCertificate(" << id << ", " << trustlvl << ")" << std::endl;
#endif
return this->privateTrustCertificate(id, trustlvl);
if (1 != privateTrustCertificate(id, trustlvl))
{
storeAllKeys_locked();
return false;
}
/* reload stuff now ... */
storeAllKeys_locked();
return true;
}
bool AuthGPG::SignData(std::string input, std::string &sign)
@ -1349,13 +1350,11 @@ bool AuthGPG::SignDataBin(std::string input, unsigned char *sign, unsigned int *
}
bool AuthGPG::SignDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) {
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
return DoOwnSignature_locked(data, datalen,
sign, signlen);
}
bool AuthGPG::VerifySignBin(const void *data, uint32_t datalen, unsigned char *sign, unsigned int signlen, std::string withfingerprint) {
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
return VerifySignature_locked(data, datalen,
sign, signlen, withfingerprint);
}
@ -1365,11 +1364,11 @@ bool AuthGPG::VerifySignBin(const void *data, uint32_t datalen, unsigned char *s
int AuthGPG::privateSignCertificate(std::string id)
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
/* The key should be in Others list and not in Peers list ??
* Once the key is signed, it moves from Others to Peers list ???
*/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
certmap::iterator it;
if (mKeyList.end() == (it = mKeyList.find(id)))
{
@ -1393,7 +1392,6 @@ int AuthGPG::privateSignCertificate(std::string id)
return 0;
}
if(GPG_ERR_NO_ERROR != (ERR = gpgme_op_edit(CTX, signKey, keySignCallback, &params, out))) {
return 0;
}
@ -1404,7 +1402,7 @@ int AuthGPG::privateSignCertificate(std::string id)
/* revoke the signature on Certificate */
int AuthGPG::privateRevokeCertificate(std::string id)
{
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
//RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
return 0;
}
@ -1417,6 +1415,7 @@ int AuthGPG::privateTrustCertificate(std::string id, int trustlvl)
return 0;
}
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
gpgcert trustCert = mKeyList.find(id)->second;
gpgme_key_t trustKey = trustCert.key;
std::string trustString;
@ -1438,9 +1437,6 @@ int AuthGPG::privateTrustCertificate(std::string id, int trustlvl)
//the key ref has changed, we got to get rid of the old reference.
trustCert.key = NULL;
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
storeAllKeys_locked();
return 1;
}
@ -2076,7 +2072,7 @@ std::list<RsItem*> AuthGPG::saveList(bool& cleanup)
std::cerr << "AuthGPG::saveList() called" << std::endl ;
#endif
RsStackMutex stack(pgpMtx); /******* LOCKED ******/
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::READ_LOCK); /******* LOCKED ******/
cleanup = true ;
std::list<RsItem*> lst ;
@ -2108,10 +2104,9 @@ bool AuthGPG::loadList(std::list<RsItem*> load)
std::cerr << "AuthGPG::loadList() Item Count: " << load.size() << std::endl;
#endif
RsStackMutex stack(pgpMtx); /****** STACK LOCK MUTEX *******/
storeAllKeys_locked();
RsStackReadWriteMutex stack(pgpMtx, RsReadWriteMutex::WRITE_LOCK); /******* LOCKED ******/
/* load the list of accepted gpg keys */
std::list<RsItem *>::iterator it;
for(it = load.begin(); it != load.end(); it++) {

View File

@ -233,7 +233,7 @@ private:
static AuthGPG *instance_gpg; // pointeur vers le singleton
RsMutex pgpMtx;
RsReadWriteMutex pgpMtx;
/* Below is protected via the mutex */
certmap mKeyList;

View File

@ -1894,21 +1894,24 @@ int pem_passwd_cb(char *buf, int size, int rwflag, void *password)
return(strlen(buf));
}
bool AuthSSL::LocalStoreCert(X509* x509) {
bool AuthSSL::LocalStoreCert(X509* x509)
{
//store the certificate in the local cert list
std::string peerId;
if(!getX509id(x509, peerId))
{
#ifdef AUTHSSL_DEBUG
#ifdef AUTHSSL_DEBUG
std::cerr << "AuthSSL::LocalStoreCert() Cannot retrieve peer id from certificate." << std::endl;
#endif
#endif
return false;
}
if (peerId != mOwnId) {
if (mCerts[peerId]) {
#ifdef AUTHSSL_DEBUG
if (peerId != mOwnId)
{
if (mCerts[peerId])
{
#ifdef AUTHSSL_DEBUG
std::cerr << "AuthSSL::LocalStoreCert() get duplicate for " << mCerts[peerId]->id << std::endl;
#endif
#endif
/* have a duplicate */
/* check that they are exact */
if (0 != X509_cmp(mCerts[peerId]->certificate, x509))
@ -1918,16 +1921,18 @@ bool AuthSSL::LocalStoreCert(X509* x509) {
std::cerr << std::endl;
return false;
}
} else {
}
else
{
RsStackMutex stack(sslMtx); /******* LOCKED ******/
#ifdef AUTHSSL_DEBUG
#ifdef AUTHSSL_DEBUG
std::cerr << "AuthSSL::LocalStoreCert() storing certificate for " << peerId << std::endl;
#endif
#endif
//have a deep copy of the x509 cert
BIO *bp = BIO_new(BIO_s_mem());
PEM_write_bio_X509(bp, x509);
X509 *certCopy = PEM_read_bio_X509(bp, NULL, 0, NULL);certCopy->cert_info->key->pkey;
X509 *certCopy = PEM_read_bio_X509(bp, NULL, 0, NULL);
mCerts[peerId] = new sslcert(certCopy, peerId);
/* cert->cert_info->key->pkey is NULL until we call SSL_CTX_use_certificate(),
@ -1936,19 +1941,21 @@ bool AuthSSL::LocalStoreCert(X509* x509) {
SSL_CTX_set_cipher_list(newSslctx, "DEFAULT");
SSL_CTX_use_certificate(newSslctx, mCerts[peerId]->certificate);
#ifdef AUTHSSL_DEBUG
#ifdef AUTHSSL_DEBUG
std::cerr << "AuthSSL::LocalStoreCert() storing certificate with public key : " << mCerts[peerId]->certificate->cert_info->key->pkey << std::endl;
#endif
#endif
IndicateConfigChanged();
}
} else {
#ifdef AUTHSSL_DEBUG
#ifdef AUTHSSL_DEBUG
std::cerr << "AuthSSL::LocalStoreCert() not storing certificate because it's our own " << peerId << std::endl;
#endif
}
#endif
}
return true ;
}
int AuthSSL::VerifyX509Callback(int preverify_ok, X509_STORE_CTX *ctx)
{
char buf[256];

View File

@ -208,7 +208,7 @@ class NotifyBase
virtual void notifyOwnAvatarChanged() {}
virtual void notifyOwnStatusMessageChanged() {}
virtual std::string askForPassword(const std::string& key_details) { return "" ;}
virtual std::string askForPassword(const std::string& key_details,bool prev_is_bad) { return "" ;}
};
const int NOTIFY_LIST_NEIGHBOURS = 1;

View File

@ -297,10 +297,11 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored)
/******************************** WINDOWS/UNIX SPECIFIC PART ******************/
int c;
/* getopt info: every availiable option is listet here. if it is followed by a ':' it
std::string prefPgpName = "";
/* getopt info: every availiable option is listed here. if it is followed by a ':' it
needs an argument. If it is followed by a '::' the argument is optional.
*/
while((c = getopt(argc, argv,"hesamui:p:c:w:l:d:")) != -1)
while((c = getopt(argc, argv,"hesamui:p:c:w:l:d:U:")) != -1)
{
switch (c)
{
@ -366,6 +367,11 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored)
std::cerr << "Opt for External Port Mode";
std::cerr << std::endl;
break;
case 'U':
prefPgpName = optarg;
std::cerr << "Opt for User Id ";
std::cerr << std::endl;
break;
case 'h':
std::cerr << "Help: " << std::endl;
std::cerr << "The commandline options are for retroshare-nogui, a headless server in a shell, or systems without QT." << std::endl << std::endl;
@ -380,6 +386,7 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored)
std::cerr << "-m StartMinimised" << std::endl;
std::cerr << "-u Only listen to UDP" << std::endl;
std::cerr << "-e Use a forwarded external Port" << std::endl << std::endl;
std::cerr << "-U [User Name] Sets Account to Use, Useful when Autologin is enabled" << std::endl;
std::cerr << "Example" << std::endl;
std::cerr << "./retroshare-nogui -wmysecretpassword -e" << std::endl;
exit(1);
@ -479,6 +486,27 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored)
std::list<accountId>::iterator it;
getAvailableAccounts(RsInitConfig::accountIds);
// if a different user id has been passed to cmd line check for that instead
bool pgpNameFound = false;
if(prefPgpName != ""){
for(it = RsInitConfig::accountIds.begin() ; it!= RsInitConfig::accountIds.end() ; it++){
if(prefPgpName == it->pgpName){
RsInitConfig::preferedId = it->sslId;
pgpNameFound = true;
}
}
if(!pgpNameFound){
std::cerr << "Invalid User name -U pgpName not Found" << std::endl;
exit(1);
}
}
/* check that preferedId */
std::string userName;
std::string userId;
@ -498,6 +526,7 @@ int RsInit::InitRetroShare(int argcIgnored, char **argvIgnored)
{
std::cerr << "No Existing User" << std::endl;
RsInitConfig::preferedId == "";
}
@ -1205,7 +1234,7 @@ int RsInit::LoadCertificates(bool autoLoginNT)
RsInitConfig::passwd = "";
create_configinit(RsInitConfig::basedir, RsInitConfig::preferedId);
//don't autorise the password callback again because it will lead to deadlock due to QT reentrance
AuthGPG::getAuthGPG()->setAutorisePasswordCallbackNotify(false);
// AuthGPG::getAuthGPG()->setAutorisePasswordCallbackNotify(false);
return 1;
}

View File

@ -144,3 +144,49 @@ void RsQueueThread::run()
}
}
RsReadWriteMutex::RsReadWriteMutex():readLocks(0) {
}
void RsReadWriteMutex::readLock() {
internalCounterMtx.lock();//lock internal read counter
if (readLocks == 0) {
lock(); //lock normal mutex
}
readLocks++;
internalCounterMtx.unlock();
}
void RsReadWriteMutex::readUnlock() {
internalCounterMtx.lock();//lock internal read counter
if (readLocks == 1) {
unlock();
}
if (readLocks != 0) {
readLocks--;
}
internalCounterMtx.unlock();
}
void RsReadWriteMutex::writeLock() {
lock();
}
void RsReadWriteMutex::writeUnlock() {
unlock();
}
void RsReadWriteMutex::rwlock(uint32_t type) {
if (type & READ_LOCK) {
readLock();
} else {
writeLock();
}
}
void RsReadWriteMutex::rwunlock(uint32_t type) {
if (type & READ_LOCK) {
readUnlock();
} else {
writeUnlock();
}
}

View File

@ -98,6 +98,41 @@ class RsStackMutex
RsMutex &mMtx;
};
class RsReadWriteMutex: public RsMutex
{
public:
RsReadWriteMutex();
void readLock();
void readUnlock();
void writeLock();
void writeUnlock();
void rwlock(uint32_t type);
void rwunlock(uint32_t type);
const static uint32_t READ_LOCK = 0x0001;
const static uint32_t WRITE_LOCK = 0x0002;
private:
int readLocks;
RsMutex internalCounterMtx;
};
class RsStackReadWriteMutex
{
public:
RsStackReadWriteMutex(RsReadWriteMutex &mtx): mMtx(mtx) { mMtx.writeLock(); writeLock = true;}
RsStackReadWriteMutex(RsReadWriteMutex &mtx, uint32_t type): mMtx(mtx) { if (type == RsReadWriteMutex::READ_LOCK) {mMtx.readLock(); writeLock = false;} else {mMtx.writeLock(); writeLock = true;} }
~RsStackReadWriteMutex() { if(writeLock) {mMtx.writeUnlock();} else {mMtx.readUnlock();} }
private:
RsReadWriteMutex &mMtx;
bool writeLock;
};
class RsThread;
/* to create a thread! */

View File

@ -329,6 +329,9 @@ void MainWindow::displaySystrayMsg(const QString& title,const QString& msg)
void MainWindow::updateStatus()
{
// This call is essential to remove locks due to QEventLoop re-entrance while asking gpg passwds. Dont' remove it!
if(RsAutoUpdatePage::eventsLocked())
return ;
if (ratesstatus)
ratesstatus->getRatesStatus();

View File

@ -710,6 +710,9 @@ void NetworkDialog::displayInfoLogMenu(const QPoint& pos) {
void NetworkDialog::getNetworkStatus()
{
if(RsAutoUpdatePage::eventsLocked())
return ;
rsiface->lockData(); /* Lock Interface */
/* now the extra bit .... switch on check boxes */
@ -766,6 +769,9 @@ void NetworkDialog::getNetworkStatus()
void NetworkDialog::updateNetworkStatus()
{
if(RsAutoUpdatePage::eventsLocked())
return ;
rsiface->lockData(); /* Lock Interface */
/* now the extra bit .... switch on check boxes */

View File

@ -3,6 +3,8 @@
#include "RsAutoUpdatePage.h"
#include "MessengerWindow.h"
bool RsAutoUpdatePage::_locked = false ;
RsAutoUpdatePage::RsAutoUpdatePage(int ms_update_period,QWidget *parent)
: MainPage(parent)
{
@ -16,6 +18,7 @@ RsAutoUpdatePage::RsAutoUpdatePage(int ms_update_period,QWidget *parent)
void RsAutoUpdatePage::showEvent(QShowEvent *event)
{
//std::cout << "RsAutoUpdatePage::showEvent() In show event !!" << std::endl ;
if(!_locked)
updateDisplay();
}
@ -23,7 +26,7 @@ void RsAutoUpdatePage::timerUpdate()
{
// only update when the widget is visible.
//
if(!isVisible())
if(_locked || !isVisible())
return ;
updateDisplay();
@ -31,3 +34,6 @@ void RsAutoUpdatePage::timerUpdate()
update() ; // Qt flush
}
void RsAutoUpdatePage::lockAllEvents() { _locked = true ; }
void RsAutoUpdatePage::unlockAllEvents() { _locked = false ; }
bool RsAutoUpdatePage::eventsLocked() { return _locked ; }

View File

@ -22,6 +22,10 @@ class RsAutoUpdatePage: public MainPage
virtual void updateDisplay() {}
static void lockAllEvents() ;
static void unlockAllEvents() ;
static bool eventsLocked() ;
protected:
virtual void showEvent(QShowEvent *e) ;
@ -30,4 +34,7 @@ class RsAutoUpdatePage: public MainPage
private:
QTimer *_timer ;
static bool _locked ;
};

View File

@ -211,7 +211,7 @@ void StartDialog::notSecureWarning() {
if(ui.autologin_checkbox->isChecked()){
QMessageBox::StandardButton sb = QMessageBox::warning ( NULL,
tr("Insecure"),
tr("Auto Login is not Secure: Password stored on disk"),
tr("Auto Login is not so much secure:\n - Your SSL certificate will be stored unprotected. \n - Your PGP key will however not be stored."),
QMessageBox::Ok);
}

View File

@ -24,6 +24,7 @@
#include <rshare.h>
#include <control/bandwidthevent.h>
#include "bwgraph.h"
#include <gui/RsAutoUpdatePage.h>
#include "rsiface/rsiface.h"
#include <sstream>
@ -119,6 +120,9 @@ BandwidthGraph::timerEvent( QTimerEvent * )
void
BandwidthGraph::updategraphstatus( )
{
if(RsAutoUpdatePage::eventsLocked())
return ;
/* set users/friends/network */
float downKb = 0;
float upKb = 0;

View File

@ -42,13 +42,18 @@ void NotifyQt::notifyOwnAvatarChanged()
emit ownAvatarChanged() ;
}
std::string NotifyQt::askForPassword(const std::string& key_details)
std::string NotifyQt::askForPassword(const std::string& key_details,bool prev_is_bad)
{
return QInputDialog::getText(NULL, tr("GPG key passphrase"),
tr("Please enter the password to unlock the following GPG key:\n") + QString::fromStdString(key_details),
QLineEdit::Password,
NULL, NULL).toStdString();
RsAutoUpdatePage::lockAllEvents() ;
std::string res = QInputDialog::getText(NULL, tr("GPG key passphrase"),
(prev_is_bad?tr("Wrong password !\n\n"):QString()) +
tr("Please enter the password to unlock the following GPG key:\n") + QString::fromStdString(key_details), QLineEdit::Password, NULL, NULL).toStdString();
RsAutoUpdatePage::unlockAllEvents() ;
return res ;
}
void NotifyQt::notifyOwnStatusMessageChanged()

View File

@ -41,7 +41,7 @@ class NotifyQt: public QObject, public NotifyBase
virtual void notifyOwnAvatarChanged() ;
virtual void notifyOwnStatusMessageChanged() ;
virtual std::string askForPassword(const std::string& key_details) ;
virtual std::string askForPassword(const std::string& key_details,bool prev_is_bad) ;
signals:
// It's beneficial to send info to the GUI using signals, because signals are thread-safe