diff --git a/libretroshare/src/pgp/pgphandler.cc b/libretroshare/src/pgp/pgphandler.cc index 6b12e91ac..10c32219f 100644 --- a/libretroshare/src/pgp/pgphandler.cc +++ b/libretroshare/src/pgp/pgphandler.cc @@ -4,6 +4,7 @@ #include #include #include +#include extern "C" { #include @@ -16,8 +17,10 @@ extern "C" { } #include "pgphandler.h" #include "retroshare/rsiface.h" // For rsicontrol. -#include "util/rsdir.h" // For rsicontrol. -#include "util/pgpkey.h" // For rsicontrol. +#include "util/rsdir.h" +#include "util/pgpkey.h" + +#define DEBUG_PGPHANDLER PassphraseCallback PGPHandler::_passphrase_callback = NULL ; @@ -127,6 +130,7 @@ PGPHandler::PGPHandler(const std::string& pubring, const std::string& secring,co ++i ; } + _pubring_last_update_time = time(NULL) ; std::cerr << "Pubring read successfully." << std::endl; if(secring_exist) @@ -143,6 +147,7 @@ PGPHandler::PGPHandler(const std::string& pubring, const std::string& secring,co initCertificateInfo(_secret_keyring_map[ PGPIdType(keydata->key_id).toStdString() ],keydata,i) ; ++i ; } + _secring_last_update_time = time(NULL) ; std::cerr << "Secring read successfully." << std::endl; @@ -197,6 +202,9 @@ void PGPHandler::validateAndUpdateSignatures(PGPCertificateInfo& cert,const ops_ ops_validate_result_t* result=(ops_validate_result_t*)ops_mallocz(sizeof *result); ops_boolean_t res = ops_validate_key_signatures(result,keydata,_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. // @@ -209,7 +217,9 @@ void PGPHandler::validateAndUpdateSignatures(PGPCertificateInfo& cert,const ops_ PGPHandler::~PGPHandler() { +#ifdef DEBUG_PGPHANDLER std::cerr << "Freeing PGPHandler. Deleting keyrings." << std::endl; +#endif // no need to free the the _map_ elements. They will be freed by the following calls: // @@ -222,7 +232,9 @@ PGPHandler::~PGPHandler() bool PGPHandler::printKeys() const { +#ifdef DEBUG_PGPHANDLER std::cerr << "Printing details of all " << std::dec << _public_keyring_map.size() << " keys: " << std::endl; +#endif for(std::map::const_iterator it(_public_keyring_map.begin()); it != _public_keyring_map.end(); it++) { @@ -274,21 +286,19 @@ bool PGPHandler::availableGPGCertificatesWithPrivateKeys(std::list& i int i=0 ; while( (keydata = ops_keyring_get_key_by_index(_secring,i++)) != NULL ) - { - // check that the key is in the pubring as well - - if(ops_keyring_find_key_by_id(_pubring,keydata->key_id) != NULL) + if(ops_keyring_find_key_by_id(_pubring,keydata->key_id) != NULL) // check that the key is in the pubring as well + { if(keydata->key.pkey.algorithm == OPS_PKA_RSA) ids.push_back(PGPIdType(keydata->key_id)) ; +#ifdef DEBUG_PGPHANDLER else std::cerr << "Skipping keypair " << PGPIdType(keydata->key_id).toStdString() << ", unsupported algorithm: " << keydata->key.pkey.algorithm << std::endl; - } +#endif + } return true ; } - - bool PGPHandler::GeneratePGPCertificate(const std::string& name, const std::string& email, const std::string& passwd, PGPIdType& pgpId, std::string& errString) { static const int KEY_NUMBITS = 2048 ; @@ -324,7 +334,7 @@ bool PGPHandler::GeneratePGPCertificate(const std::string& name, const std::stri ops_keyring_t *tmp_keyring = allocateOPSKeyring() ; if(! ops_keyring_read_from_mem(tmp_keyring, ops_false, buf)) { - std::cerr << "Cannot re-read key from memory!!" << std::endl; + std::cerr << "(EE) Cannot re-read key from memory!!" << std::endl; return false ; } ops_teardown_memory_write(cinfo,buf); // cleanup memory @@ -335,14 +345,18 @@ bool PGPHandler::GeneratePGPCertificate(const std::string& name, const std::stri addNewKeyToOPSKeyring(_secring,tmp_keyring->keys[0]) ; initCertificateInfo(_secret_keyring_map[ pgpId.toStdString() ],&tmp_keyring->keys[0],_secring->nkeys-1) ; +#ifdef DEBUG_PGPHANDLER std::cerr << "Added new secret key with id " << pgpId.toStdString() << " to secret keyring." << std::endl; +#endif // 5 - copy the private key to the public keyring addNewKeyToOPSKeyring(_pubring,tmp_keyring->keys[0]) ; initCertificateInfo(_public_keyring_map[ pgpId.toStdString() ],&tmp_keyring->keys[0],_pubring->nkeys-1) ; +#ifdef DEBUG_PGPHANDLER std::cerr << "Added new public key with id " << pgpId.toStdString() << " to public keyring." << std::endl; +#endif // 6 - clean @@ -421,7 +435,9 @@ void PGPHandler::addNewKeyToOPSKeyring(ops_keyring_t *kr,const ops_keydata_t& ke bool PGPHandler::LoadCertificateFromString(const std::string& pgp_cert,PGPIdType& id,std::string& error_string) { +#ifdef DEBUG_PGPHANDLER std::cerr << "Reading new key from string: " << std::endl; +#endif ops_keyring_t *tmp_keyring = allocateOPSKeyring(); ops_memory_t *mem = ops_memory_new() ; @@ -442,39 +458,21 @@ bool PGPHandler::LoadCertificateFromString(const std::string& pgp_cert,PGPIdType free(mem) ; error_string.clear() ; +#ifdef DEBUG_PGPHANDLER std::cerr << " Key read correctly: " << std::endl; +#endif ops_keyring_list(tmp_keyring) ; const ops_keydata_t *keydata = NULL ; int i=0 ; while( (keydata = ops_keyring_get_key_by_index(tmp_keyring,i++)) != NULL ) - { - id = PGPIdType(keydata->key_id) ; - - std::cerr << " id: " << id.toStdString() << std::endl; - - // See if the key is already in the keyring - const ops_keydata_t *existing_key ; - std::map::const_iterator res = _public_keyring_map.find(id.toStdString()) ; - - if(res == _public_keyring_map.end() || (existing_key = ops_keyring_get_key_by_index(_pubring,res->second._key_index)) == NULL) - { - std::cerr << " Key is new. Adding it to keyring" << std::endl; - addNewKeyToOPSKeyring(_pubring,*keydata) ; // the key is new. - } - else - { - std::cerr << " Key exists. Merging signatures." << std::endl; - if(mergeKeySignatures(const_cast(existing_key),keydata) ) - _pubring_changed = true ; - } - - initCertificateInfo(_public_keyring_map[id.toStdString()],keydata,_pubring->nkeys-1) ; - validateAndUpdateSignatures(_public_keyring_map[id.toStdString()],keydata) ; - } + if(addOrMergeKey(_pubring,_public_keyring_map,keydata)) + _pubring_changed = true ; +#ifdef DEBUG_PGPHANDLER std::cerr << " Added the key in the main public keyring." << std::endl; +#endif ops_keyring_free(tmp_keyring) ; free(tmp_keyring) ; @@ -484,20 +482,56 @@ bool PGPHandler::LoadCertificateFromString(const std::string& pgp_cert,PGPIdType return true ; } -bool PGPHandler::writePublicKeyring() +bool PGPHandler::addOrMergeKey(ops_keyring_t *keyring,std::map& kmap,const ops_keydata_t *keydata) { - RsStackFileLock flck(_pgp_lock_filename) ; // locks access to pgp directory + bool ret = false ; + PGPIdType id(keydata->key_id) ; - _pubring_changed = false ; - return ops_write_keyring_to_file(_pubring,ops_false,_pubring_path.c_str()) ; -} +#ifdef DEBUG_PGPHANDLER + std::cerr << "AddOrMergeKey():" << std::endl; + std::cerr << " id: " << id.toStdString() << std::endl; +#endif -bool PGPHandler::writeSecretKeyring() -{ - RsStackFileLock flck(_pgp_lock_filename) ; // locks access to pgp directory + // See if the key is already in the keyring + const ops_keydata_t *existing_key = NULL; + std::map::const_iterator res = kmap.find(id.toStdString()) ; - _secring_changed = false ; - return ops_write_keyring_to_file(_secring,ops_false,_secring_path.c_str()) ; + // Checks that + // - the key is referenced by keyid + // - the map is initialized + // - the fingerprint matches! + // + if(res == kmap.end() || (existing_key = ops_keyring_get_key_by_index(keyring,res->second._key_index)) == NULL) + { +#ifdef DEBUG_PGPHANDLER + std::cerr << " Key is new. Adding it to keyring" << std::endl; +#endif + addNewKeyToOPSKeyring(keyring,*keydata) ; // the key is new. + initCertificateInfo(kmap[id.toStdString()],keydata,keyring->nkeys-1) ; + existing_key = &(keyring->keys[keyring->nkeys-1]) ; + ret = true ; + } + else + { + if(memcmp(existing_key->fingerprint.fingerprint, keydata->fingerprint.fingerprint,KEY_FINGERPRINT_SIZE)) + { + std::cerr << "(EE) attempt to merge key with identical id, but different fingerprint!" << std::endl; + return false ; + } + +#ifdef DEBUG_PGPHANDLER + std::cerr << " Key exists. Merging signatures." << std::endl; +#endif + ret = mergeKeySignatures(const_cast(existing_key),keydata) ; + + if(ret) + initCertificateInfo(kmap[id.toStdString()],existing_key,res->second._key_index) ; + } + + if(ret) + validateAndUpdateSignatures(kmap[id.toStdString()],existing_key) ; + + return ret ; } bool PGPHandler::encryptTextToFile(const PGPIdType& key_id,const std::string& text,const std::string& outfile) @@ -543,8 +577,10 @@ bool PGPHandler::decryptTextFromFile(const PGPIdType& key_id,std::string& text,c fclose(f) ; +#ifdef DEBUG_PGPHANDLER std::cerr << "PGPHandler::decryptTextFromFile: read a file of length " << std::dec << buf.length() << std::endl; std::cerr << "buf=\"" << buf << "\"" << std::endl; +#endif int out_length ; ops_boolean_t res = ops_decrypt_memory((const unsigned char *)buf.c_str(),buf.length(),&out_buf,&out_length,_secring,ops_true,cb_get_passphrase) ; @@ -633,7 +669,9 @@ bool PGPHandler::VerifySignBin(const void *literal_data, uint32_t literal_data_l return false ; } +#ifdef DEBUG_PGPHANDLER std::cerr << "Verifying signature from fingerprint " << key_fingerprint.toStdString() << ", length " << std::dec << sign_len << ", literal data length = " << literal_data_length << std::endl; +#endif return ops_validate_detached_signature(literal_data,literal_data_length,sign,sign_len,key) ; } @@ -688,7 +726,7 @@ bool operator<(const ops_packet_t& p1,const ops_packet_t& p2) if(p1.length > p2.length) return false ; - for(int i=0;ikey_id).toStdString() << std::endl; +#endif std::set dst_packets ; - for(int i=0;inpackets;++i) dst_packets.insert(dst->packets[i]) ; + for(uint32_t i=0;inpackets;++i) dst_packets.insert(dst->packets[i]) ; std::set to_add ; - for(int i=0;inpackets;++i) + for(uint32_t i=0;inpackets;++i) if(dst_packets.find(src->packets[i]) == dst_packets.end()) { uint8_t tag ; @@ -719,24 +759,28 @@ bool PGPHandler::mergeKeySignatures(ops_keydata_t *dst,const ops_keydata_t *src) if(tag == PGPKeyParser::PGP_PACKET_TAG_SIGNATURE) to_add.insert(src->packets[i]) ; +#ifdef DEBUG_PGPHANDLER else std::cerr << " Packet with tag 0x" << std::hex << (int)(src->packets[i].raw[0]) << std::dec << " not merged, because it is not a signature." << std::endl; +#endif } for(std::set::const_iterator it(to_add.begin());it!=to_add.end();++it) { +#ifdef DEBUG_PGPHANDLER std::cerr << " Adding packet with tag 0x" << std::hex << (int)(*it).raw[0] << std::dec << std::endl; +#endif ops_add_packet_to_keydata(dst,&*it) ; } return to_add.size() > 0 ; } -void PGPHandler::privateTrustCertificate(const PGPIdType& id,int trustlvl) +bool PGPHandler::privateTrustCertificate(const PGPIdType& id,int trustlvl) { - if(trustlvl < 0 || trustlvl > 6) + if(trustlvl < 0 || trustlvl >= 6 || trustlvl == 1) { std::cerr << "Invalid trust level " << trustlvl << " passed to privateTrustCertificate." << std::endl; - return ; + return false ; } std::map::iterator it = _public_keyring_map.find(id.toStdString()); @@ -744,13 +788,15 @@ void PGPHandler::privateTrustCertificate(const PGPIdType& id,int trustlvl) if(it == _public_keyring_map.end()) { std::cerr << "(EE) Key id " << id.toStdString() << " not in the keyring. Can't setup trust level." << std::endl; - return ; + return false ; } - if( it->second._validLvl != trustlvl ) + if( it->second._validLvl != (int)trustlvl ) _trustdb_changed = true ; it->second._validLvl = trustlvl ; + + return true ; } struct PrivateTrustPacket @@ -763,7 +809,9 @@ struct PrivateTrustPacket void PGPHandler::locked_readPrivateTrustDatabase() { FILE *fdb = fopen(_trustdb_path.c_str(),"rb") ; +#ifdef DEBUG_PGPHANDLER std::cerr << "PGPHandler: Reading private trust database." << std::endl; +#endif if(fdb == NULL) { @@ -794,15 +842,17 @@ void PGPHandler::locked_readPrivateTrustDatabase() fclose(fdb) ; } -void PGPHandler::locked_writePrivateTrustDatabase() +bool PGPHandler::locked_writePrivateTrustDatabase() { FILE *fdb = fopen((_trustdb_path+".tmp").c_str(),"wb") ; +#ifdef DEBUG_PGPHANDLER std::cerr << "PGPHandler: Reading private trust database." << std::endl; +#endif if(fdb == NULL) { std::cerr << " (EE) Can't open private trust database file " << _trustdb_path << " for write. Giving up!" << std::endl ; - return ; + return false; } PrivateTrustPacket trustpacket ; @@ -815,13 +865,182 @@ void PGPHandler::locked_writePrivateTrustDatabase() { std::cerr << " (EE) Cannot write to trust database " << _trustdb_path << ". Disc full, or quota exceeded ? Leaving database untouched." << std::endl; fclose(fdb) ; - return ; + return false; } } fclose(fdb) ; if(!RsDirUtil::renameFile(_trustdb_path+".tmp",_trustdb_path)) + { std::cerr << " (EE) Cannot move temp file " << _trustdb_path+".tmp" << ". Bad write permissions?" << std::endl; + return false ; + } + else + return true ; } +bool PGPHandler::syncDatabase() +{ + RsStackFileLock flck(_pgp_lock_filename) ; // lock access to PGP directory. + +#ifdef DEBUG_PGPHANDLER + std::cerr << "Sync-ing keyrings." << std::endl; +#endif + locked_syncPublicKeyring() ; + locked_syncSecretKeyring() ; + + // Now sync the trust database as well. + // + locked_syncTrustDatabase() ; + +#ifdef DEBUG_PGPHANDLER + std::cerr << "Done. " << std::endl; +#endif + return true ; +} + +bool PGPHandler::locked_syncPublicKeyring() +{ + struct stat64 buf ; +#ifdef WINDOWS_SYS + std::wstring wfullname; + librs::util::ConvertUtf8ToUtf16(_pubring_path, wfullname); + if(-1 == _wstati64(wfullname.c_str(), &buf)) +#else + if(-1 == stat64(_pubring_path.c_str(), &buf)) +#endif + { + std::cerr << "PGPHandler::syncDatabase(): can't stat file " << _pubring_path << ". Can't sync public keyring." << std::endl; + return false; + } + + if(_pubring_last_update_time < buf.st_mtime) + { + std::cerr << "Detected change on disk of public keyring. Merging!" << std::endl ; + + mergeKeyringFromDisk(_pubring,_public_keyring_map,_pubring_path) ; + _pubring_last_update_time = buf.st_mtime ; + } + + // Now check if the pubring was locally modified, which needs saving it again + if(_pubring_changed) + { + std::cerr << "Local changes in public keyring. Writing to disk..." << std::endl; + if(!ops_write_keyring_to_file(_pubring,ops_false,_pubring_path.c_str())) + std::cerr << "Cannot write public keyring. Disk full? Disk quota exceeded?" << std::endl; + else + { + std::cerr << "Done." << std::endl; + _pubring_last_update_time = time(NULL) ; // should we get this value from the disk instead?? + _pubring_changed = false ; + } + } + return true ; +} + +bool PGPHandler::locked_syncSecretKeyring() +{ + struct stat64 buf ; +#ifdef WINDOWS_SYS + librs::util::ConvertUtf8ToUtf16(_secring_path, wfullname); + if(-1 == _wstati64(wfullname.c_str(), &buf)) +#else + if(-1 == stat64(_secring_path.c_str(), &buf)) +#endif + { + std::cerr << "PGPHandler::syncDatabase(): can't stat file " << _secring_path << ". Can't sync secret keyring." << std::endl; + return false; + } +#ifdef TODO + if(_secring_last_update_time < buf.st_mtime) + { + std::cerr << "Detected change on disk of secret keyring. " << std::endl ; + secring_changed_on_disk = true ; + + mergeKeyringFromDisk(_secring,_secret_keyring_map,_secring_path) ; + _secring_last_update_time = buf.st_mtime ; + } +#endif + if(_secring_changed) + { + std::cerr << "Local changes in secret keyring. Writing to disk..." << std::endl; + if(!ops_write_keyring_to_file(_secring,ops_false,_secring_path.c_str())) + { + std::cerr << "Cannot write secret keyring. Disk full? Disk quota exceeded?" << std::endl; + return false ; + } + else + { + std::cerr << "Done." << std::endl; + _secring_last_update_time = time(NULL) ; // should we get this value from the disk instead?? + _secring_changed = false ; + } + } + return true ; +} +bool PGPHandler::locked_syncTrustDatabase() +{ + struct stat64 buf ; + std::wstring wfullname; +#ifdef WINDOWS_SYS + librs::util::ConvertUtf8ToUtf16(_trustdb_path, wfullname); + if(-1 == _wstati64(wfullname.c_str(), &buf)) +#else + if(-1 == stat64(_trustdb_path.c_str(), &buf)) +#endif + { + std::cerr << "PGPHandler::syncDatabase(): can't stat file " << _trustdb_path << ". Will force write it." << std::endl; + _trustdb_changed = true ; // we force write of trust database if it does not exist. + } + + if(_trustdb_last_update_time < buf.st_mtime) + { + std::cerr << "Detected change on disk of trust database. " << std::endl ; + + locked_readPrivateTrustDatabase(); + _trustdb_last_update_time = time(NULL) ; + } + + if(_trustdb_changed) + { + std::cerr << "Local changes in trust database. Writing to disk..." << std::endl; + if(!locked_writePrivateTrustDatabase()) + std::cerr << "Cannot write trust database. Disk full? Disk quota exceeded?" << std::endl; + else + { + std::cerr << "Done." << std::endl; + _trustdb_last_update_time = time(NULL) ; + _trustdb_changed = false ; + } + } + return true ; +} +void PGPHandler::mergeKeyringFromDisk( ops_keyring_t *keyring, + std::map& kmap, + const std::string& keyring_file) +{ +#ifdef DEBUG_PGPHANDLER + std::cerr << "Merging keyring " << keyring_file << " from disk to memory." << std::endl; +#endif + + // 1 - load keyring into a temporary keyring list. + ops_keyring_t *tmp_keyring = PGPHandler::allocateOPSKeyring() ; + + if(ops_false == ops_keyring_read_from_file(tmp_keyring, false, keyring_file.c_str())) + { + std::cerr << "PGPHandler::mergeKeyringFromDisk(): cannot read keyring. File corrupted?" ; + ops_keyring_free(tmp_keyring) ; + return ; + } + + // 2 - load new keys and merge existing key signatures + + for(int i=0;inkeys;++i) + addOrMergeKey(keyring,kmap,&tmp_keyring->keys[i]) ;// we dont' account for the return value. This is disk merging, not local changes. + + // 4 - clean + ops_keyring_free(tmp_keyring) ; +} + + diff --git a/libretroshare/src/pgp/pgphandler.h b/libretroshare/src/pgp/pgphandler.h index 9d767442c..acefb73fc 100644 --- a/libretroshare/src/pgp/pgphandler.h +++ b/libretroshare/src/pgp/pgphandler.h @@ -48,6 +48,12 @@ class PGPCertificateInfo static const uint32_t PGP_CERTIFICATE_FLAG_HAS_OWN_SIGNATURE = 0x0002 ; static const uint32_t PGP_CERTIFICATE_FLAG_HAS_SIGNED_ME = 0x0004 ; static const uint32_t PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM = 0x0008 ; // set when the key is not RSA, so that RS avoids to use it. + + static const uint8_t PGP_CERTIFICATE_TRUST_UNDEFINED = 0x00 ; + static const uint8_t PGP_CERTIFICATE_TRUST_NEVER = 0x02 ; + static const uint8_t PGP_CERTIFICATE_TRUST_MARGINALLY = 0x03 ; + static const uint8_t PGP_CERTIFICATE_TRUST_FULLY = 0x04 ; + static const uint8_t PGP_CERTIFICATE_TRUST_ULTIMATE = 0x05 ; }; class PGPHandler @@ -84,7 +90,7 @@ class PGPHandler bool isKeySupported(const PGPIdType& id) const ; - void privateTrustCertificate(const PGPIdType& id,int valid_level) ; + bool privateTrustCertificate(const PGPIdType& id,int valid_level) ; // Write keyring bool publicKeyringChanged() const { return _pubring_changed ; } @@ -105,6 +111,15 @@ class PGPHandler // Debug stuff. virtual bool printKeys() const ; + // Syncs the keyrings and trust database between memory and disk. The algorithm is: + // 1 - lock the keyrings + // 2 - compare file modification dates with last writing date + // - if file is modified, load it, and merge with memory + // 3 - look into memory modification flags + // - if flag says keyring has changed, write to disk + // + bool syncDatabase() ; + private: void initCertificateInfo(PGPCertificateInfo& cert,const ops_keydata_t *keydata,uint32_t i) ; void validateAndUpdateSignatures(PGPCertificateInfo& cert,const ops_keydata_t *keydata) ; @@ -113,7 +128,14 @@ class PGPHandler const ops_keydata_t *getSecretKey(const PGPIdType&) const ; void locked_readPrivateTrustDatabase() ; - void locked_writePrivateTrustDatabase() ; + bool locked_writePrivateTrustDatabase() ; + + bool locked_syncPublicKeyring() ; + bool locked_syncSecretKeyring() ; + bool locked_syncTrustDatabase() ; + + void mergeKeyringFromDisk(ops_keyring_t *keyring, std::map& kmap, const std::string& keyring_file) ; + bool addOrMergeKey(ops_keyring_t *keyring,std::map& kmap,const ops_keydata_t *keydata) ; // Members. // @@ -134,6 +156,10 @@ class PGPHandler bool _secring_changed ; bool _trustdb_changed ; + time_t _pubring_last_update_time ; + time_t _secring_last_update_time ; + time_t _trustdb_last_update_time ; + // Helper functions. // static std::string makeRadixEncodedPGPKey(const ops_keydata_t *key) ; diff --git a/libretroshare/src/pqi/authgpg.cc b/libretroshare/src/pqi/authgpg.cc index 5f5a04d04..4e23e1191 100644 --- a/libretroshare/src/pqi/authgpg.cc +++ b/libretroshare/src/pqi/authgpg.cc @@ -53,15 +53,6 @@ void cleanupZombies(int numkill); // function to cleanup zombies under OSX. //#define GPG_DEBUG 1 -/* Turn a set of parameters into a string */ -static std::string setKeyPairParams(bool useRsa, unsigned int blen, - std::string name, std::string comment, std::string email, - std::string inPassphrase); - -// static gpg_error_t keySignCallback(void *, gpgme_status_code_t, const char *, int); -// static gpg_error_t trustCallback(void *, gpgme_status_code_t, const char *, int); -// static std::string ProcessPGPmeError(gpgme_error_t ERR); - /* Function to sign X509_REQ via GPGme. */ bool AuthGPG::decryptTextFromFile(std::string& text,const std::string& inputfile) @@ -111,10 +102,10 @@ void AuthGPG::exit() AuthGPG::AuthGPG(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(CONFIG_TYPE_AUTHGPG), PGPHandler(path_to_public_keyring,path_to_secret_keyring,path_to_trustdb,pgp_lock_file), + gpgMtxService("AuthGPG-service"), gpgMtxEngine("AuthGPG-engine"), gpgMtxData("AuthGPG-data"), - gpgKeySelected(false), - gpgMtxService("AuthGPG-service") + gpgKeySelected(false) { start(); } @@ -178,13 +169,20 @@ void AuthGPG::run() /* every 100 milliseconds */ processServices(); -#ifdef SUSPENDED - /* every minute */ - if (++count >= 600) { - storeAllKeys_tick(); - count = 0; + + /* every ten seconds */ + if (++count >= 100) + { + 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. + // + PGPHandler::syncDatabase() ; + count = 0; } -#endif } } @@ -281,294 +279,6 @@ void AuthGPG::processServices() delete operation; } -#ifdef TO_REMOVE -// store all keys in map mKeyList to avoid callin gpgme exe repeatedly -bool AuthGPG::storeAllKeys() -{ -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::storeAllKeys()" << std::endl; -#endif - - std::string ownGpgId; - - /* store member variables locally */ - { - RsStackMutex stack(gpgMtxData); - - if (!gpgmeInit) - { - std::cerr << "AuthGPG::storeAllKeys() Error since GPG is not initialised" << std::endl; - return false; - } - - mStoreKeyTime = time(NULL); - ownGpgId = mOwnGpgId; - } - - /* read keys from gpg to local list */ - std::list keyList; - - { -#ifdef GPG_DEBUG - std::cerr << "AuthGPG::storeAllKeys() clearing existing ones" << std::endl; -#endif - - gpg_error_t ERR; - - RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ - - /* enable SIG mode */ - gpgme_keylist_mode_t origmode = gpgme_get_keylist_mode(CTX); - gpgme_keylist_mode_t mode = origmode | GPGME_KEYLIST_MODE_SIGS; - - gpgme_set_keylist_mode(CTX, mode); - - /* store keys */ - gpgme_key_t KEY = NULL; - - /* Initiates a key listing 0 = All Keys */ - if (GPG_ERR_NO_ERROR != gpgme_op_keylist_start (CTX, "", 0)) - { - std::cerr << "AuthGPG::storeAllKeys() Error iterating through KeyList" << std::endl; - // if (rsicontrol != NULL) { - // rsicontrol->getNotify().notifyErrorMsg(0,0,"Error reading gpg keyring, cannot acess key list."); - // } - gpgme_set_keylist_mode(CTX, origmode); - return false; - } - - /* Loop until end of key */ - ERR = gpgme_op_keylist_next (CTX, &KEY); - if (GPG_ERR_NO_ERROR != ERR) { - std::cerr << "AuthGPG::storeAllKeys() didn't find any gpg key in the keyring" << std::endl; - // if (rsicontrol != NULL) { - // rsicontrol->getNotify().notifyErrorMsg(0,0,"Error reading gpg keyring, cannot find any key in the list."); - // } - gpgme_set_keylist_mode(CTX, origmode); - return false; - } - - for(int i = 0;GPG_ERR_NO_ERROR == ERR; i++) - { - /* store in pqiAuthDetails */ - gpgcert nu; - - /* NB subkeys is a linked list and can contain multiple keys. - * first key is primary. - */ - - if ((!KEY->subkeys) || (!KEY->uids)) - { - std::cerr << "AuthGPG::storeAllKeys() Invalid Key in List... skipping" << std::endl; - continue; - } - - /* In general MainSubKey is used to sign all others! - * Don't really need to worry about other ids either. - */ - gpgme_subkey_t mainsubkey = KEY->subkeys; - nu.id = mainsubkey->keyid; - nu.fpr = mainsubkey->fpr; - -#ifdef GPG_DEBUG - std::cerr << "MAIN KEYID: " << nu.id << " FPR: " << nu.fpr << std::endl; - - gpgme_subkey_t subkeylist = KEY->subkeys; - while(subkeylist != NULL) - { - std::cerr << "\tKEYID: " << subkeylist->keyid << " FPR: " << subkeylist->fpr << std::endl; - - subkeylist = subkeylist->next; - } -#endif - - - /* 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; - gpgme_key_sig_t mainsiglist = mainuid->signatures; - - nu.ownsign = false; - while(mainsiglist != NULL) - { - if (mainsiglist->status == GPG_ERR_NO_ERROR) - { - /* add as a signature ... even if the - * we haven't go the peer yet. - * (might be yet to come). - */ - std::string keyid = mainsiglist->keyid; - if (nu.signers.end() == std::find( - nu.signers.begin(), - nu.signers.end(),keyid)) - { - nu.signers.push_back(keyid); - } - if (keyid == ownGpgId) { - nu.ownsign = true; - } - } - mainsiglist = mainsiglist->next; - } - -#ifdef GPG_DEBUG - gpgme_user_id_t uidlist = KEY->uids; - while(uidlist != NULL) - { - std::cerr << "\tUID: " << uidlist->uid; - std::cerr << " NAME: " << uidlist->name; - std::cerr << " EMAIL: " << uidlist->email; - std::cerr << " VALIDITY: " << uidlist->validity; - std::cerr << std::endl; - gpgme_key_sig_t usiglist = uidlist->signatures; - while(usiglist != NULL) - { - std::cerr << "\t\tSIG KEYID: " << usiglist->keyid; - std::cerr << " UID: " << usiglist->uid; - std::cerr << " NAME: " << usiglist->name; - std::cerr << " EMAIL: " << usiglist->email; - std::cerr << " VALIDITY: " << (usiglist->status == GPG_ERR_NO_ERROR); - std::cerr << std::endl; - - usiglist = usiglist->next; - } - - uidlist = uidlist->next; - } -#endif - - /* signatures are attached to uids... but only supplied - * if GPGME_KEYLIST_MODE_SIGS is on. - * signature notation supplied is GPGME_KEYLIST_MODE_SIG_NOTATION is on - */ - nu.trustLvl = KEY->owner_trust; - nu.validLvl = mainuid->validity; - - /* grab a reference, so the key remains */ - gpgme_key_ref(KEY); - nu.key = KEY; - - /* store in map */ - keyList.push_back(nu); -#ifdef GPG_DEBUG - std::cerr << "nu.name" << nu.name << std::endl; - std::cerr << "nu.trustLvl" << nu.trustLvl << std::endl; - std::cerr << "nu.accept_connection" << nu.accept_connection << std::endl; -#endif - - ERR = gpgme_op_keylist_next (CTX, &KEY); - } - - if (GPG_ERR_NO_ERROR != gpgme_op_keylist_end(CTX)) - { - std::cerr << "Error ending KeyList" << std::endl; - gpgme_set_keylist_mode(CTX, origmode); - return false; - } - - gpgme_set_keylist_mode(CTX, origmode); - } - - /* process read gpg keys and store it in member */ - std::list gpg_change_trust_list; - - { - RsStackMutex stack(gpgMtxData); - - //let's start a new list - mKeyList.clear(); - - for (std::list::iterator it = keyList.begin(); it != keyList.end(); it++) { - gpgcert &nu = *it; - - std::map::iterator itAccept; - if (mAcceptToConnectMap.end() != (itAccept = mAcceptToConnectMap.find(nu.id))) { - nu.accept_connection = itAccept->second; - } else { - nu.accept_connection = false; - mAcceptToConnectMap[nu.id] = false; - } - - if (nu.trustLvl < 2 && nu.accept_connection) { - //add it to the list of key that we will force the trust to 2 - gpg_change_trust_list.push_back(nu.id); - } - - /* grab a reference, so the key remains */ - gpgme_key_ref(nu.key); - - mKeyList[nu.id] = nu; - - //store own key - if (nu.id == mOwnGpgId) { - /* grab a reference, so the key remains */ - gpgme_key_ref(nu.key); - - gpgme_key_unref(mOwnGpgCert.key); - mOwnGpgCert = nu; - } - } - } - - std::list::iterator it; - for(it = gpg_change_trust_list.begin(); it != gpg_change_trust_list.end(); it++) - { - privateTrustCertificate(*it, 3); - } - - return true; - -} -std::string ProcessPGPmeError(gpgme_error_t ERR) -{ - gpgme_err_code_t code = gpgme_err_code(ERR); - gpgme_err_source_t src = gpgme_err_source(ERR); - - std::ostringstream ss ; - - if(code > 0) - { - ss << "GPGme ERROR: Code: " << code << " Source: " << src << std::endl; - ss << "GPGme ERROR: " << gpgme_strerror(ERR) << std::endl; - } - else - return std::string("Unknown error") ; - - return ss.str() ; -} - -void print_pgpme_verify_summary(unsigned int summary) -{ - std::cerr << "\tFLAGS:"; - if (summary & GPGME_SIGSUM_VALID) - std::cerr << " VALID "; - if (summary & GPGME_SIGSUM_GREEN) - std::cerr << " GREEN "; - if (summary & GPGME_SIGSUM_RED) - std::cerr << " RED "; - if (summary & GPGME_SIGSUM_KEY_REVOKED) - std::cerr << " KEY_REVOKED "; - if (summary & GPGME_SIGSUM_KEY_EXPIRED) - std::cerr << " KEY_EXPIRED "; - if (summary & GPGME_SIGSUM_SIG_EXPIRED) - std::cerr << " SIG_EXPIRED "; - if (summary & GPGME_SIGSUM_KEY_MISSING) - std::cerr << " KEY_MISSING "; - if (summary & GPGME_SIGSUM_CRL_MISSING) - std::cerr << " CRL_MISSING "; - if (summary & GPGME_SIGSUM_CRL_TOO_OLD) - std::cerr << " CRL_TOO_OLD "; - if (summary & GPGME_SIGSUM_BAD_POLICY) - std::cerr << " BAD_POLICY "; - if (summary & GPGME_SIGSUM_SYS_ERROR) - std::cerr << " SYS_ERROR "; - std::cerr << std::endl; -} -#endif - bool AuthGPG::DoOwnSignature(const void *data, unsigned int datalen, void *buf_sigout, unsigned int *outl) { return PGPHandler::SignDataBin(mOwnGpgId,data,datalen,(unsigned char *)buf_sigout,outl) ; @@ -678,46 +388,6 @@ bool AuthGPG::getGPGAllList(std::list &ids) return true; } -#ifdef TO_REMOVE -bool AuthGPG::decryptText(gpgme_data_t CIPHER, gpgme_data_t PLAIN) -{ - RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ - gpgme_set_armor (CTX, 1); - gpg_error_t ERR; - - cleanupZombies(2); // cleanup zombies under OSX. (Called before gpgme operation) - - if (GPG_ERR_NO_ERROR != (ERR = gpgme_op_decrypt (CTX, CIPHER, PLAIN))) - { - std::cerr << "AuthGPG::decryptText() Error decrypting text" << std::endl; - std::cerr << ProcessPGPmeError(ERR) << std::endl; - return false; - } - - return true; -} - -bool AuthGPG::encryptText(gpgme_data_t PLAIN, gpgme_data_t CIPHER) -{ - RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ - gpgme_encrypt_flags_t* flags = new gpgme_encrypt_flags_t(); - gpgme_key_t keys[2] = {mOwnGpgCert.key, NULL}; - gpgme_set_armor (CTX, 1); - gpg_error_t ERR; - - cleanupZombies(2); // cleanup zombies under OSX. (Called before gpgme operation) - - if (GPG_ERR_NO_ERROR != (ERR = gpgme_op_encrypt(CTX, keys, *flags, PLAIN, CIPHER))) - { - std::cerr << "AuthGPG::encryptText() Error encrypting text" << std::endl; - std::cerr << ProcessPGPmeError(ERR) << std::endl; - return false; - } - - return true; -} -#endif - bool AuthGPG::isKeySupported(const std::string& id) const { const PGPCertificateInfo *pc = PGPHandler::getCertificateInfo(PGPIdType(id)) ; @@ -1041,596 +711,15 @@ int AuthGPG::privateRevokeCertificate(const std::string &/*id*/) int AuthGPG::privateTrustCertificate(const std::string &id, int trustlvl) { /* The certificate should be in Peers list ??? */ - if(!isGPGAccepted(id)) { + if(!isGPGAccepted(id)) + { std::cerr << "Invalid Certificate" << std::endl; return 0; } - std::cerr << __PRETTY_FUNCTION__ << ": to be implemented!" << std::endl; - - PGPHandler::privateTrustCertificate(PGPIdType(id),trustlvl) ; - -// { -// gpgcert trustCert; -// { -// RsStackMutex stack(gpgMtxData); -// -// trustCert = mKeyList.find(id)->second; -// } /******* UNLOCKED ******/ -// -// RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ -// -// gpgme_key_t trustKey = trustCert.key; -// std::string trustString; -// std::ostringstream trustStrOut; -// trustStrOut << trustlvl; -// class TrustParams sparams(trustStrOut.str()); -// class EditParams params(TRUST_START, &sparams); -// gpgme_data_t out; -// gpg_error_t ERR; -// -// if(GPG_ERR_NO_ERROR != (ERR = gpgme_data_new(&out))) { -// return 0; -// } -// -// if(GPG_ERR_NO_ERROR != (ERR = gpgme_op_edit(CTX, trustKey, trustCallback, ¶ms, out))) { -// gpgme_data_release(out); -// return 0; -// } -// -// gpgme_data_release(out); -// -// //the key ref has changed, we got to get rid of the old reference. -// trustCert.key = NULL; -// } -// -// storeAllKeys(); - - return 1; + return PGPHandler::privateTrustCertificate(PGPIdType(id),trustlvl) ; } -static std::string setKeyPairParams(bool useRsa, unsigned int blen, - std::string name, std::string comment, std::string email, - std::string inPassphrase) -{ - std::ostringstream params; - params << ""<< std::endl; - if (useRsa) - { - params << "Key-Type: RSA"<< std::endl; - if (blen < 1024) - { -#ifdef GPG_DEBUG - std::cerr << "Weak Key... strengthing..."<< std::endl; -#endif - blen = 1024; - } - blen = ((blen / 512) * 512); /* make multiple of 512 */ - params << "Key-Length: "<< blen << std::endl; - } - else - { - params << "Key-Type: DSA"<< std::endl; - params << "Key-Length: 1024"<< std::endl; - params << "Subkey-Type: ELG-E"<< std::endl; - params << "Subkey-Length: 1024"<< std::endl; - } - params << "Name-Real: "<< name << std::endl; - params << "Name-Comment: "<< comment << std::endl; - params << "Name-Email: "<< email << std::endl; - params << "Expire-Date: 0"<< std::endl; - params << "Passphrase: "<< inPassphrase << std::endl; - params << ""<< std::endl; - - return params.str(); -} - - -/* Author: Shiva - * This function returns the key macthing the user parameters - * from the keyring - */ - -#ifdef UNUSED_CODE -static gpgme_key_t getKey(gpgme_ctx_t CTX, std::string name, std::string comment, std::string email) { - - gpgme_key_t key; - gpgme_user_id_t user; - - /* Initiates a key listing */ - if (GPG_ERR_NO_ERROR != gpgme_op_keylist_start (CTX, "", 0)) - { - std::cerr << "Error iterating through KeyList"; - std::cerr << std::endl; - return false; - - } - - /* Loop until end of key */ - for(int i = 0;(GPG_ERR_NO_ERROR == gpgme_op_keylist_next (CTX, &key)); i++) - { - user = key->uids; - - while(user != NULL) { - if((name.size() && name == user->name) && (comment.size() && comment == user->comment) && \ - (email.size() && email == user->email)) - { - /* grab a reference to the key */ - gpgme_op_keylist_end(CTX); - if (GPG_ERR_NO_ERROR != gpgme_op_keylist_end(CTX)) - { - std::cerr << "Error ending KeyList"; - std::cerr << std::endl; - } - gpgme_key_ref(key); - return key; - } - user = user->next; - } - } - - if (GPG_ERR_NO_ERROR != gpgme_op_keylist_end(CTX)) - { - std::cerr << "Error ending KeyList" << std::endl; - } - return NULL; -} -#endif - -#ifdef TO_REMOVE -/* Callback function for key signing */ - -static gpg_error_t keySignCallback(void *opaque, gpgme_status_code_t status, \ - const char *args, int fd) { - - class EditParams *params = (class EditParams *)opaque; - class SignParams *sparams = (class SignParams *)params->oParams; - const char *result = NULL; -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback status: %d args: %s, params->state: %d\n", status, args, params->state); - - /* printf stuff out */ - if (status == GPGME_STATUS_EOF) - fprintf(stderr,"keySignCallback GPGME_STATUS_EOF\n"); - if (status == GPGME_STATUS_GOT_IT) - fprintf(stderr,"keySignCallback GPGME_STATUS_GOT_IT\n"); - if (status == GPGME_STATUS_USERID_HINT) - fprintf(stderr,"keySignCallback GPGME_STATUS_USERID_HINT\n"); - if (status == GPGME_STATUS_NEED_PASSPHRASE) - fprintf(stderr,"keySignCallback GPGME_STATUS_NEED_PASSPHRASE\n"); - if (status == GPGME_STATUS_GOOD_PASSPHRASE) - fprintf(stderr,"keySignCallback GPGME_STATUS_GOOD_PASSPHRASE\n"); - if (status == GPGME_STATUS_BAD_PASSPHRASE) - fprintf(stderr,"keySignCallback GPGME_STATUS_BAD_PASSPHRASE\n"); - if (status == GPGME_STATUS_GET_LINE) - fprintf(stderr,"keySignCallback GPGME_STATUS_GET_LINE\n"); - if (status == GPGME_STATUS_GET_BOOL) - fprintf(stderr,"keySignCallback GPGME_STATUS_GET_BOOL\n"); - if (status == GPGME_STATUS_ALREADY_SIGNED) - fprintf(stderr,"keySignCallback GPGME_STATUS_ALREADY_SIGNED\n"); - - /* printf stuff out */ - if (params->state == SIGN_START) - fprintf(stderr,"keySignCallback params->state SIGN_START\n"); - if (params->state == SIGN_COMMAND) - fprintf(stderr,"keySignCallback params->state SIGN_COMMAND\n"); - if (params->state == SIGN_UIDS) - fprintf(stderr,"keySignCallback params->state SIGN_UIDS\n"); - if (params->state == SIGN_SET_EXPIRE) - fprintf(stderr,"keySignCallback params->state SIGN_SET_EXPIRE\n"); - if (params->state == SIGN_SET_CHECK_LEVEL) - fprintf(stderr,"keySignCallback params->state SIGN_SET_CHECK_LEVEL\n"); - if (params->state == SIGN_CONFIRM) - fprintf(stderr,"keySignCallback params->state SIGN_CONFIRM\n"); - if (params->state == SIGN_QUIT) - fprintf(stderr,"keySignCallback params->state SIGN_QUIT\n"); - if (params->state == SIGN_ENTER_PASSPHRASE) - fprintf(stderr,"keySignCallback params->state SIGN_ENTER_PASSPHRASE\n"); - if (params->state == SIGN_ERROR) - fprintf(stderr,"keySignCallback params->state SIGN_ERROR"); -#endif - - - if(status == GPGME_STATUS_EOF || - status == GPGME_STATUS_GOT_IT || - status == GPGME_STATUS_USERID_HINT || - status == GPGME_STATUS_NEED_PASSPHRASE || - // status == GPGME_STATUS_GOOD_PASSPHRASE || - status == GPGME_STATUS_BAD_PASSPHRASE) { - - - fprintf(stderr,"keySignCallback Error status\n"); - std::cerr << ProcessPGPmeError(params->err) << std::endl; - - return params->err; - } - - switch (params->state) - { - case SIGN_START: -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback SIGN_START\n"); -#endif - - if (status == GPGME_STATUS_GET_LINE && - (!std::string("keyedit.prompt").compare(args))) - { - params->state = SIGN_COMMAND; - result = "sign"; - } - else - { - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case SIGN_COMMAND: -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback SIGN_COMMAND\n"); -#endif - - if (status == GPGME_STATUS_GET_BOOL && - (!std::string("keyedit.sign_all.okay").compare(args))) - { - params->state = SIGN_UIDS; - result = "Y"; - } - else if (status == GPGME_STATUS_GET_BOOL && - (!std::string("sign_uid.okay").compare(args))) - { - params->state = SIGN_ENTER_PASSPHRASE; - result = "Y"; - } - else if (status == GPGME_STATUS_GET_LINE && - (!std::string("sign_uid.expire").compare(args))) - { - params->state = SIGN_SET_EXPIRE; - result = "Y"; - } - else if (status == GPGME_STATUS_GET_LINE && - (!std::string("sign_uid.class").compare(args))) - { - params->state = SIGN_SET_CHECK_LEVEL; - result = sparams->checkLvl.c_str(); - } - else if (status == GPGME_STATUS_ALREADY_SIGNED) - { - /* The key has already been signed with this key */ - params->state = SIGN_QUIT; - result = "quit"; - } - else if (status == GPGME_STATUS_GET_LINE && - (!std::string("keyedit.prompt").compare(args))) - { - /* Failed sign: expired key */ - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_UNUSABLE_PUBKEY); - } - else - { - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case SIGN_UIDS: -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback SIGN_UIDS\n"); -#endif - - if (status == GPGME_STATUS_GET_LINE && - (!std::string("sign_uid.expire").compare(args))) - { - params->state = SIGN_SET_EXPIRE; - result = "Y"; - } - else if (status == GPGME_STATUS_GET_LINE && - (!std::string("sign_uid.class").compare(args))) - { - params->state = SIGN_SET_CHECK_LEVEL; - result = sparams->checkLvl.c_str(); - } - else if (status == GPGME_STATUS_GET_BOOL && - (!std::string("sign_uid.okay").compare(args))) - { - params->state = SIGN_ENTER_PASSPHRASE; - result = "Y"; - } - else if (status == GPGME_STATUS_GET_LINE && - (!std::string("keyedit.prompt").compare(args))) - { - /* Failed sign: expired key */ - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_UNUSABLE_PUBKEY); - } - else - { - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case SIGN_SET_EXPIRE: -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback SIGN_SET_EXPIRE\n"); -#endif - - if (status == GPGME_STATUS_GET_LINE && - (!std::string("sign_uid.class").compare(args))) - { - params->state = SIGN_SET_CHECK_LEVEL; - result = sparams->checkLvl.c_str(); - } - else - { - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case SIGN_SET_CHECK_LEVEL: -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback SIGN_SET_CHECK_LEVEL\n"); -#endif - - if (status == GPGME_STATUS_GET_BOOL && - (!std::string("sign_uid.okay").compare(args))) - { - params->state = SIGN_ENTER_PASSPHRASE; - result = "Y"; - } - else - { - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case SIGN_ENTER_PASSPHRASE: -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback SIGN_ENTER_PASSPHRASE\n"); -#endif - - if (status == GPGME_STATUS_GOOD_PASSPHRASE) - { - params->state = SIGN_CONFIRM; - } - else - { - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case SIGN_CONFIRM: -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback SIGN_CONFIRM\n"); -#endif - - if (status == GPGME_STATUS_GET_LINE && - (!std::string("keyedit.prompt").compare(args))) - { - params->state = SIGN_QUIT; - result = "quit"; - } - else - { - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case SIGN_QUIT: -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback SIGN_QUIT\n"); -#endif - - if (status == GPGME_STATUS_GET_BOOL && - (!std::string("keyedit.save.okay").compare(args))) - { - params->state = SIGN_SAVE; - result = "Y"; - } - else - { - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case SIGN_ERROR: -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback SIGN_ERROR\n"); -#endif - - if (status == GPGME_STATUS_GET_LINE && - (!std::string("keyedit.prompt").compare(args))) - { - /* Go to quit operation state */ - params->state = SIGN_QUIT; - result = "quit"; - } - else - { - params->state = SIGN_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - default: - fprintf(stderr,"keySignCallback UNKNOWN state\n"); - break; - } - - if (result) - { -#ifdef GPG_DEBUG - fprintf(stderr,"keySignCallback result:%s\n", result); -#endif -#ifndef WINDOWS_SYS - if (*result) - { - write (fd, result, strlen (result)); - write (fd, "\n", 1); - } -#else - DWORD written = 0; - HANDLE winFd = (HANDLE) fd; - if (*result) - { - WriteFile(winFd, result, strlen(result), &written, NULL); - WriteFile(winFd, "\n", 1, &written, NULL); - } -#endif - - } - - fprintf(stderr,"keySignCallback Error status\n"); - std::cerr << ProcessPGPmeError(params->err) << std::endl; - - return params->err; -} -#endif - - -#ifdef TO_REMOVE -/* Callback function for assigning trust level */ - -static gpgme_error_t trustCallback(void *opaque, gpgme_status_code_t status, \ - const char *args, int fd) { - - class EditParams *params = (class EditParams *)opaque; - class TrustParams *tparams = (class TrustParams *)params->oParams; - const char *result = NULL; - - /* printf stuff out */ -#ifdef GPG_DEBUG - if (status == GPGME_STATUS_EOF) - fprintf(stderr,"keySignCallback GPGME_STATUS_EOF\n"); - if (status == GPGME_STATUS_GOT_IT) - fprintf(stderr,"keySignCallback GPGME_STATUS_GOT_IT\n"); - if (status == GPGME_STATUS_USERID_HINT) - fprintf(stderr,"keySignCallback GPGME_STATUS_USERID_HINT\n"); - if (status == GPGME_STATUS_NEED_PASSPHRASE) - fprintf(stderr,"keySignCallback GPGME_STATUS_NEED_PASSPHRASE\n"); - if (status == GPGME_STATUS_GOOD_PASSPHRASE) - fprintf(stderr,"keySignCallback GPGME_STATUS_GOOD_PASSPHRASE\n"); - if (status == GPGME_STATUS_BAD_PASSPHRASE) - fprintf(stderr,"keySignCallback GPGME_STATUS_BAD_PASSPHRASE\n"); - if (status == GPGME_STATUS_GET_LINE) - fprintf(stderr,"keySignCallback GPGME_STATUS_GET_LINE\n"); - if (status == GPGME_STATUS_GET_BOOL) - fprintf(stderr,"keySignCallback GPGME_STATUS_GET_BOOL \n"); - if (status == GPGME_STATUS_ALREADY_SIGNED) - fprintf(stderr,"keySignCallback GPGME_STATUS_ALREADY_SIGNED\n"); - - /* printf stuff out */ - if (params->state == TRUST_START) - fprintf(stderr,"keySignCallback params->state TRUST_START\n"); - if (params->state == TRUST_COMMAND) - fprintf(stderr,"keySignCallback params->state TRUST_COMMAND\n"); - if (params->state == TRUST_VALUE) - fprintf(stderr,"keySignCallback params->state TRUST_VALUE\n"); - if (params->state == TRUST_REALLY_ULTIMATE) - fprintf(stderr,"keySignCallback params->state TRUST_REALLY_ULTIMATE\n"); - if (params->state == TRUST_QUIT) - fprintf(stderr,"keySignCallback params->state TRUST_QUIT\n"); - if (params->state == TRUST_ERROR) - fprintf(stderr,"keySignCallback params->state TRUST_ERROR\n"); -#endif - - - if(status == GPGME_STATUS_EOF || - status == GPGME_STATUS_GOT_IT) { - return params->err; - } - - - switch (params->state) - { - case TRUST_START: - if (status == GPGME_STATUS_GET_LINE && - (!std::string("keyedit.prompt").compare(args))) { - params->state = TRUST_COMMAND; - result = "trust"; - } else { - params->state = TRUST_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - - case TRUST_COMMAND: - if (status == GPGME_STATUS_GET_LINE && - (!std::string("edit_ownertrust.value").compare(args))) { - params->state = TRUST_VALUE; - result = tparams->trustLvl.c_str();; - } else { - params->state = TRUST_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case TRUST_VALUE: - if (status == GPGME_STATUS_GET_LINE && - (!std::string("keyedit.prompt").compare(args))) { - params->state = TRUST_QUIT; - result = "quit"; - } - else if (status == GPGME_STATUS_GET_BOOL && - (!std::string("edit_ownertrust.set_ultimate.okay").compare(args))) { - params->state = TRUST_REALLY_ULTIMATE; - result = "Y"; - } - else { - params->state = TRUST_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case TRUST_REALLY_ULTIMATE: - if (status == GPGME_STATUS_GET_LINE && - (!std::string("keyedit.prompt").compare(args))) { - params->state = TRUST_QUIT; - result = "quit"; - } else { - params->state = TRUST_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case TRUST_QUIT: - if (status == GPGME_STATUS_GET_BOOL && - (!std::string("keyedit.save.okay").compare(args))) { - params->state = TRUST_SAVE; - result = "Y"; - } else { - params->state = TRUST_ERROR; - params->err = gpg_error (GPG_ERR_GENERAL); - } - break; - case TRUST_ERROR: - if (status == GPGME_STATUS_GET_LINE && - (!std::string("keyedit.prompt").compare(args))) { - /* Go to quit operation state */ - params->state = TRUST_QUIT; - result = "quit"; - } else { - params->state = TRUST_ERROR; - } - break; - } - - if (result) - { -#ifndef WINDOWS_SYS - if (*result) - write (fd, result, strlen (result)); - write (fd, "\n", 1); -#else - DWORD written = 0; - HANDLE winFd = (HANDLE) fd; - if (*result) - WriteFile(winFd, result, strlen (result), &written, NULL); - WriteFile(winFd, "\n", 1, &written, NULL); -#endif -#ifdef GPG_DEBUG - std::cerr << "trustCallback() result : " << result << std::endl; -#endif - } - - return params->err; -} -#endif - // -----------------------------------------------------------------------------------// // -------------------------------- Config functions ------------------------------ // // -----------------------------------------------------------------------------------// @@ -1716,52 +805,4 @@ bool AuthGPG::addService(AuthGPGService *service) return true; } -#ifdef TO_REMOVE -/***************************** HACK to Cleanup OSX Zombies *****************************/ - - -#ifdef __APPLE__ -#include -#endif - -void cleanupZombies(int numkill) -{ - -#ifdef __APPLE__ - - pid_t wpid = -1; // any child. - int stat_loc = 0; - int options = WNOHANG ; - - //std::cerr << "cleanupZombies() checking for dead children"; - //std::cerr << std::endl; - - int i; - for(i = 0; i < numkill; i++) - { - pid_t childpid = waitpid(wpid, &stat_loc, options); - - if (childpid > 0) - { - std::cerr << "cleanupZombies() Found stopped child with pid: " << childpid; - std::cerr << std::endl; - } - else - { - //std::cerr << "cleanupZombies() No Zombies around!"; - //std::cerr << std::endl; - break; - } - } - - //std::cerr << "cleanupZombies() Killed " << i << " zombies"; - //std::cerr << std::endl; -#else - /* remove unused parameter warnings */ - (void) numkill; -#endif - - return; -} -#endif diff --git a/openpgpsdk/src/create.c b/openpgpsdk/src/create.c index 14e6e5693..38d552a5b 100644 --- a/openpgpsdk/src/create.c +++ b/openpgpsdk/src/create.c @@ -220,195 +220,195 @@ static ops_boolean_t write_secret_key_body(const ops_secret_key_t *key, const unsigned char* passphrase, const size_t pplen, ops_create_info_t *info) - { - /* RFC4880 Section 5.5.3 Secret-Key Packet Formats */ +{ + /* RFC4880 Section 5.5.3 Secret-Key Packet Formats */ - ops_crypt_t crypt; - ops_hash_t hash; - unsigned char hashed[OPS_SHA1_HASH_SIZE]; - unsigned char session_key[CAST_KEY_LENGTH]; - unsigned int done=0; - unsigned int i=0; + ops_crypt_t crypt; + ops_hash_t hash; + unsigned char hashed[OPS_SHA1_HASH_SIZE]; + unsigned char session_key[CAST_KEY_LENGTH]; + unsigned int done=0; + unsigned int i=0; - if(!write_public_key_body(&key->public_key,info)) - return ops_false; + if(!write_public_key_body(&key->public_key,info)) + return ops_false; - assert(key->s2k_usage==OPS_S2KU_ENCRYPTED_AND_HASHED); /* = 254 */ - if(!ops_write_scalar(key->s2k_usage,1,info)) - return ops_false; - - assert(key->algorithm==OPS_SA_CAST5); - if (!ops_write_scalar(key->algorithm,1,info)) - return ops_false; + assert(key->s2k_usage==OPS_S2KU_ENCRYPTED_AND_HASHED); /* = 254 */ + if(!ops_write_scalar(key->s2k_usage,1,info)) + return ops_false; - assert(key->s2k_specifier==OPS_S2KS_SIMPLE - || key->s2k_specifier==OPS_S2KS_SALTED); // = 1 \todo could also be iterated-and-salted - if (!ops_write_scalar(key->s2k_specifier,1,info)) - return ops_false; - - assert(key->hash_algorithm==OPS_HASH_SHA1); - if (!ops_write_scalar(key->hash_algorithm,1,info)) - return ops_false; - - switch(key->s2k_specifier) - { - case OPS_S2KS_SIMPLE: - // nothing more to do - break; + assert(key->algorithm==OPS_SA_CAST5); + if (!ops_write_scalar(key->algorithm,1,info)) + return ops_false; - case OPS_S2KS_SALTED: - // 8-octet salt value - ops_random((void *)&key->salt[0],OPS_SALT_SIZE); - if (!ops_write(key->salt, OPS_SALT_SIZE, info)) - return ops_false; - break; + assert(key->s2k_specifier==OPS_S2KS_SIMPLE + || key->s2k_specifier==OPS_S2KS_SALTED); // = 1 \todo could also be iterated-and-salted + if (!ops_write_scalar(key->s2k_specifier,1,info)) + return ops_false; - /* \todo - case OPS_S2KS_ITERATED_AND_SALTED: - // 8-octet salt value - // 1-octet count - break; - */ + assert(key->hash_algorithm==OPS_HASH_SHA1); + if (!ops_write_scalar(key->hash_algorithm,1,info)) + return ops_false; - default: - fprintf(stderr,"invalid/unsupported s2k specifier %d\n", - key->s2k_specifier); - assert(0); - } - - if (!ops_write(&key->iv[0],ops_block_size(key->algorithm),info)) - return ops_false; - - /* create the session key for encrypting the algorithm-specific fields */ - - switch(key->s2k_specifier) - { - case OPS_S2KS_SIMPLE: - case OPS_S2KS_SALTED: - // RFC4880: section 3.7.1.1 and 3.7.1.2 - - done=0; - for (i=0; donehash_algorithm); - hash.init(&hash); - - // preload if iterating - for (j=0; js2k_specifier==OPS_S2KS_SALTED) - { hash.add(&hash, key->salt, OPS_SALT_SIZE); } - - hash.add(&hash, passphrase, pplen); - hash.finish(&hash, hashed); - - // if more in hash than is needed by session key, use the - // leftmost octets - memcpy(session_key+(i*SHA_DIGEST_LENGTH), hashed, use); - done += use; - assert(done<=CAST_KEY_LENGTH); - } - - break; - - /* \todo - case OPS_S2KS_ITERATED_AND_SALTED: - // 8-octet salt value - // 1-octet count - break; - */ - - default: - fprintf(stderr,"invalid/unsupported s2k specifier %d\n", - key->s2k_specifier); - assert(0); - } - - /* use this session key to encrypt */ - - ops_crypt_any(&crypt,key->algorithm); - crypt.set_iv(&crypt, key->iv); - crypt.set_key(&crypt, session_key); - ops_encrypt_init(&crypt); - - if (debug) - { - unsigned int i=0; - fprintf(stderr,"\nWRITING:\niv="); - for (i=0; ialgorithm); i++) - { - fprintf(stderr, "%02x ", key->iv[i]); - } - fprintf(stderr,"\n"); - - fprintf(stderr,"key="); - for (i=0; ipublic_key.algorithm) + switch(key->s2k_specifier) { - // case OPS_PKA_DSA: - // return ops_write_mpi(key->key.dsa.x,info); + case OPS_S2KS_SIMPLE: + // nothing more to do + break; - case OPS_PKA_RSA: - case OPS_PKA_RSA_ENCRYPT_ONLY: - case OPS_PKA_RSA_SIGN_ONLY: + case OPS_S2KS_SALTED: + // 8-octet salt value + ops_random((void *)&key->salt[0],OPS_SALT_SIZE); + if (!ops_write(key->salt, OPS_SALT_SIZE, info)) + return ops_false; + break; - if(!ops_write_mpi(key->key.rsa.d,info) - || !ops_write_mpi(key->key.rsa.p,info) - || !ops_write_mpi(key->key.rsa.q,info) - || !ops_write_mpi(key->key.rsa.u,info)) - { - if (debug) - { fprintf(stderr,"4 x mpi not written - problem\n"); } - return ops_false; - } + /* \todo + case OPS_S2KS_ITERATED_AND_SALTED: + // 8-octet salt value + // 1-octet count + break; + */ - break; - - // case OPS_PKA_ELGAMAL: - // return ops_write_mpi(key->key.elgamal.x,info); - - default: - assert(0); - break; + default: + fprintf(stderr,"invalid/unsupported s2k specifier %d\n", + key->s2k_specifier); + assert(0); } - if(!ops_write(key->checkhash, OPS_CHECKHASH_SIZE, info)) - return ops_false; + if (!ops_write(&key->iv[0],ops_block_size(key->algorithm),info)) + return ops_false; - ops_writer_pop(info); + /* create the session key for encrypting the algorithm-specific fields */ - free(crypt.encrypt_key) ; - free(crypt.decrypt_key) ; - - return ops_true; - } + switch(key->s2k_specifier) + { + case OPS_S2KS_SIMPLE: + case OPS_S2KS_SALTED: + // RFC4880: section 3.7.1.1 and 3.7.1.2 + + done=0; + for (i=0; donehash_algorithm); + hash.init(&hash); + + // preload if iterating + for (j=0; js2k_specifier==OPS_S2KS_SALTED) + { hash.add(&hash, key->salt, OPS_SALT_SIZE); } + + hash.add(&hash, passphrase, pplen); + hash.finish(&hash, hashed); + + // if more in hash than is needed by session key, use the + // leftmost octets + memcpy(session_key+(i*SHA_DIGEST_LENGTH), hashed, use); + done += use; + assert(done<=CAST_KEY_LENGTH); + } + + break; + + /* \todo + case OPS_S2KS_ITERATED_AND_SALTED: + // 8-octet salt value + // 1-octet count + break; + */ + + default: + fprintf(stderr,"invalid/unsupported s2k specifier %d\n", + key->s2k_specifier); + assert(0); + } + + /* use this session key to encrypt */ + + ops_crypt_any(&crypt,key->algorithm); + crypt.set_iv(&crypt, key->iv); + crypt.set_key(&crypt, session_key); + ops_encrypt_init(&crypt); + + if (debug) + { + unsigned int i=0; + fprintf(stderr,"\nWRITING:\niv="); + for (i=0; ialgorithm); i++) + { + fprintf(stderr, "%02x ", key->iv[i]); + } + fprintf(stderr,"\n"); + + fprintf(stderr,"key="); + for (i=0; ipublic_key.algorithm) + { + // case OPS_PKA_DSA: + // return ops_write_mpi(key->key.dsa.x,info); + + case OPS_PKA_RSA: + case OPS_PKA_RSA_ENCRYPT_ONLY: + case OPS_PKA_RSA_SIGN_ONLY: + + if(!ops_write_mpi(key->key.rsa.d,info) + || !ops_write_mpi(key->key.rsa.p,info) + || !ops_write_mpi(key->key.rsa.q,info) + || !ops_write_mpi(key->key.rsa.u,info)) + { + if (debug) + { fprintf(stderr,"4 x mpi not written - problem\n"); } + return ops_false; + } + + break; + + // case OPS_PKA_ELGAMAL: + // return ops_write_mpi(key->key.elgamal.x,info); + + default: + assert(0); + break; + } + + if(!ops_write(key->checkhash, OPS_CHECKHASH_SIZE, info)) + return ops_false; + + ops_writer_pop(info); + + free(crypt.encrypt_key) ; + free(crypt.decrypt_key) ; + + return ops_true; +} /** diff --git a/openpgpsdk/src/openssl_crypto.c b/openpgpsdk/src/openssl_crypto.c index 25f01816c..1d70ccac9 100644 --- a/openpgpsdk/src/openssl_crypto.c +++ b/openpgpsdk/src/openssl_crypto.c @@ -393,6 +393,12 @@ ops_boolean_t ops_dsa_verify(const unsigned char *hash,size_t hash_length, osig->r=sig->r; osig->s=sig->s; + if(BN_num_bits(dsa->q) != 160) + { + fprintf(stderr,"(WW) ops_dsa_verify: openssl does only supports 'q' of 160 bits. Current is %d bits.\n",BN_num_bits(dsa->q)) ; + return ops_false ; + } + odsa=DSA_new(); odsa->p=dsa->p; odsa->q=dsa->q;