diff --git a/libresapi/src/api/RsControlModule.cpp b/libresapi/src/api/RsControlModule.cpp index b69fa2943..1d0cddd65 100644 --- a/libresapi/src/api/RsControlModule.cpp +++ b/libresapi/src/api/RsControlModule.cpp @@ -14,6 +14,8 @@ #include "GetPluginInterfaces.h" +//#define DEBUG_CONTROL_MODULE 1 + namespace resource_api{ RsControlModule::RsControlModule(int argc, char **argv, StateTokenServer* sts, ApiServer *apiserver, bool full_control): @@ -61,6 +63,9 @@ bool RsControlModule::processShouldExit() bool RsControlModule::askForPassword(const std::string &title, const std::string &key_details, bool prev_is_bad, std::string &password, bool& cancelled) { +#ifdef DEBUG_CONTROL_MODULE + std::cerr << "RsControlModule::askForPassword(): current passwd is \"" << mPassword << "\"" << std::endl; +#endif cancelled = false ; { RS_STACK_MUTEX(mDataMtx); // ********** LOCKED ********** @@ -114,7 +119,9 @@ bool RsControlModule::askForPassword(const std::string &title, const std::string void RsControlModule::run() { +#ifdef DEBUG_CONTROL_MODULE std::cerr << "RsControlModule: initialising libretroshare..." << std::endl; +#endif RsInit::InitRsConfig(); int initResult = RsInit::InitRetroShare(argc, argv, true); @@ -125,11 +132,11 @@ void RsControlModule::run() std::stringstream ss; switch (initResult) { case RS_INIT_AUTH_FAILED: - ss << "RsInit::InitRetroShare AuthGPG::InitAuth failed" << std::endl; + ss << "RsControlModule::run() AuthGPG::InitAuth failed" << std::endl; break; default: /* Unexpected return code */ - ss << "RsInit::InitRetroShare unexpected return code " << initResult << std::endl; + ss << "ControlModule::run() unexpected return code " << initResult << std::endl; break; } // FATAL ERROR, we can't recover from this. Just send the message to the user. @@ -141,9 +148,15 @@ void RsControlModule::run() RsControl::earlyInitNotificationSystem(); rsNotify->registerNotifyClient(this); +#ifdef DEBUG_CONTROL_MODULE + std::cerr << "RsControlModule::run() Entering login wait loop." << std::endl; +#endif bool login_ok = false; while(!login_ok) { +#ifdef DEBUG_CONTROL_MODULE + std::cerr << "RsControlModule::run() reseting passwd." << std::endl; +#endif { RsStackMutex stack(mDataMtx); // ********** LOCKED ********** mPassword = ""; @@ -156,15 +169,28 @@ void RsControlModule::run() bool auto_login = false; if(wait_for_account_select) - setRunState(WAITING_ACCOUNT_SELECT); + { +#ifdef DEBUG_CONTROL_MODULE + std::cerr << "RsControlModule::run() wait_for_account_select=true => setting run state to WAITING_ACCOUNT_SELECT." << std::endl; +#endif + setRunState(WAITING_ACCOUNT_SELECT); + } while(wait_for_account_select && !processShouldExit()) { +#ifdef DEBUG_CONTROL_MODULE + std::cerr << "RsControlModule::run() while(wait_for_account_select) mLoadPeerId=" << mLoadPeerId << std::endl; +#endif usleep(500*1000); RsStackMutex stack(mDataMtx); // ********** LOCKED ********** if(!mLoadPeerId.isNull()) + { wait_for_account_select = wait_for_account_select && !RsAccounts::SelectAccount(mLoadPeerId); +#ifdef DEBUG_CONTROL_MODULE + std::cerr << "RsControlModule::run() mLoadPeerId != NULL, account selection result: " << !wait_for_account_select << std::endl; +#endif + } auto_login = mAutoLoginNextTime; @@ -180,6 +206,9 @@ void RsControlModule::run() bool autoLogin = (initResult == RS_INIT_HAVE_ACCOUNT) | auto_login; std::string lockFile; +#ifdef DEBUG_CONTROL_MODULE + std::cerr << "RsControlModule::run() trying to load certificate..." << std::endl; +#endif int retVal = RsInit::LockAndLoadCertificates(autoLogin, lockFile); std::string error_string; @@ -204,16 +233,24 @@ void RsControlModule::run() std::cerr << "RsControlModule::run() LockAndLoadCertificates failed. Unexpected switch value: " << retVal << std::endl; break; } +#ifdef DEBUG_CONTROL_MODULE + std::cerr << "RsControlModule::run() Error string: \"" << error_string << "\"" << std::endl; +#endif { RsStackMutex stack(mDataMtx); // ********** LOCKED ********** mLoadPeerId.clear(); } } +#ifdef DEBUG_CONTROL_MODULE + std::cerr << "RsControlModule::run() login is ok. Starting up..." << std::endl; +#endif { RsStackMutex stack(mDataMtx); // ********** LOCKED ********** mFixedPassword = mPassword; + + std::cerr << "***Reseting mPasswd " << std::endl; mPassword = ""; } @@ -336,13 +373,17 @@ void RsControlModule::handlePassword(Request &req, Response &resp) RsStackMutex stack(mDataMtx); // ********** LOCKED ********** std::string passwd; req.mStream << makeKeyValueReference("password", passwd); - if(passwd != "" && mWantPassword) + if(passwd != "")// && mWantPassword) { // client sends password mPassword = passwd; mWantPassword = false; mStateTokenServer->replaceToken(mStateToken); + + std::cerr << "RsControlModule::handlePassword(): setting mPasswd=\"" << mPassword << "\"" << std::endl; } + else + std::cerr << "RsControlModule::handlePassword(): not setting mPasswd=\"" << mPassword << "\"!!!" << std::endl; resp.mDataStream << makeKeyValueReference("want_password", mWantPassword) diff --git a/libretroshare/src/pqi/authgpg.cc b/libretroshare/src/pqi/authgpg.cc index 1e20d6b85..32b42461a 100644 --- a/libretroshare/src/pqi/authgpg.cc +++ b/libretroshare/src/pqi/authgpg.cc @@ -20,7 +20,7 @@ * USA. * * Please report all bugs and problems to "retroshare@lunamutt.com". - * + * * */ @@ -121,12 +121,12 @@ 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(), + :p3Config(), PGPHandler(path_to_public_keyring,path_to_secret_keyring,path_to_trustdb,pgp_lock_file), gpgMtxService("AuthGPG-service"), - gpgMtxEngine("AuthGPG-engine"), + gpgMtxEngine("AuthGPG-engine"), gpgMtxData("AuthGPG-data"), - gpgKeySelected(false) + gpgKeySelected(false) { _force_sync_database = false ; mCount = 0; @@ -231,9 +231,9 @@ void AuthGPG::processServices() } AuthGPGOperationLoadOrSave *loadOrSave = dynamic_cast(operation); - if (loadOrSave) + if (loadOrSave) { - if (loadOrSave->m_load) + if (loadOrSave->m_load) { /* process load operation */ @@ -285,8 +285,8 @@ void AuthGPG::processServices() } service->setGPGOperation(loadOrSave); - } - else + } + else { #ifdef GPG_DEBUG std::cerr << "AuthGPGimpl::processServices() Unknown operation" << std::endl; @@ -313,7 +313,7 @@ bool AuthGPG::parseSignature(const void *sig, unsigned int siglen, RsPgpId& issu return PGPHandler::parseSignature((unsigned char*)sig,siglen,issuer_id) ; } -bool AuthGPG::exportProfile(const std::string& fname,const RsPgpId& exported_id) +bool AuthGPG::exportProfile(const std::string& fname,const RsPgpId& exported_id) { return PGPHandler::exportGPGKeyPair(fname,exported_id) ; } @@ -328,7 +328,7 @@ bool AuthGPG::importProfileFromString(const std::string &data, RsPgpId &gpg_id, return PGPHandler::importGPGKeyPairFromString(data, gpg_id, import_error); } - + bool AuthGPG::active() { RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ @@ -427,7 +427,7 @@ bool AuthGPG::isKeySupported(const RsPgpId& id) const return !(pc->_flags & PGPCertificateInfo::PGP_CERTIFICATE_FLAG_UNSUPPORTED_ALGORITHM) ; } -bool AuthGPG::getGPGDetails(const RsPgpId& pgp_id, RsPeerDetails &d) +bool AuthGPG::getGPGDetails(const RsPgpId& pgp_id, RsPeerDetails &d) { RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ @@ -458,7 +458,7 @@ bool AuthGPG::getGPGDetails(const RsPgpId& pgp_id, RsPeerDetails &d) return true; } -bool AuthGPG::getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&)) +bool AuthGPG::getGPGFilteredList(std::list& list,bool (*filter)(const PGPCertificateInfo&)) { RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ @@ -492,20 +492,20 @@ bool AuthGPG::getGPGSignedList(std::list &ids) // #else // certificate = PGPHandler::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 + * 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. * */ @@ -515,7 +515,7 @@ bool AuthGPG::getGPGSignedList(std::list &ids) std::string AuthGPG::SaveCertificateToString(const RsPgpId &id,bool include_signatures) { RsStackMutex stack(gpgMtxEngine); /******* LOCKED ******/ - + return PGPHandler::SaveCertificateToString(id,include_signatures) ; } @@ -536,10 +536,10 @@ bool AuthGPG::LoadCertificateFromString(const std::string &str, RsPgpId& gpg_id, /***************************************************************** * 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 + * Auth should be done... ?? not sure + * maybe * */ @@ -596,12 +596,12 @@ bool AuthGPG::TrustCertificate(const RsPgpId& id, int trustlvl) return privateTrustCertificate(id, trustlvl) ; } -bool AuthGPG::encryptDataBin(const RsPgpId& pgp_id,const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) +bool AuthGPG::encryptDataBin(const RsPgpId& pgp_id,const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) { return PGPHandler::encryptDataBin(RsPgpId(pgp_id),data,datalen,sign,signlen) ; } -bool AuthGPG::decryptDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) +bool AuthGPG::decryptDataBin(const void *data, unsigned int datalen, unsigned char *sign, unsigned int *signlen) { return PGPHandler::decryptDataBin(mOwnGpgId,data,datalen,sign,signlen) ; } @@ -610,7 +610,7 @@ bool AuthGPG::SignDataBin(const void *data, unsigned int datalen, unsigned char return DoOwnSignature(data, datalen, sign, signlen, reason); } -bool AuthGPG::VerifySignBin(const void *data, uint32_t datalen, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint) +bool AuthGPG::VerifySignBin(const void *data, uint32_t datalen, unsigned char *sign, unsigned int signlen, const PGPFingerprintType& withfingerprint) { return VerifySignature(data, datalen, sign, signlen, withfingerprint); } @@ -639,12 +639,12 @@ int AuthGPG::privateTrustCertificate(const RsPgpId& id, int trustlvl) { RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ - /* The certificate should be in Peers list ??? */ - if(!isGPGAccepted(id)) - { - std::cerr << "Invalid Certificate" << std::endl; + // 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(!isGPGAccepted(id)) return 0; - } int res = PGPHandler::privateTrustCertificate(id,trustlvl) ; _force_sync_database = true ; @@ -667,7 +667,7 @@ bool AuthGPG::saveList(bool& cleanup, std::list& lst) #ifdef GPG_DEBUG std::cerr << "AuthGPG::saveList() called" << std::endl ; #endif - std::list ids ; + std::list ids ; getGPGAcceptedList(ids) ; // needs to be done before the lock RsStackMutex stack(gpgMtxData); /******* LOCKED ******/ @@ -677,7 +677,7 @@ bool AuthGPG::saveList(bool& cleanup, std::list& lst) // Now save config for network digging strategies RsConfigKeyValueSet *vitem = new RsConfigKeyValueSet ; - for (std::list::const_iterator it(ids.begin()); it != ids.end(); ++it) + for (std::list::const_iterator it(ids.begin()); it != ids.end(); ++it) if((*it) != mOwnGpgId) // skip our own id. { RsTlvKeyValue kv; @@ -705,7 +705,7 @@ bool AuthGPG::loadList(std::list& load) for(it = load.begin(); it != load.end(); ++it) { RsConfigKeyValueSet *vitem = dynamic_cast(*it); - if(vitem) + if(vitem) { #ifdef GPG_DEBUG std::cerr << "AuthGPG::loadList() General Variable Config Item:" << std::endl; @@ -715,7 +715,7 @@ bool AuthGPG::loadList(std::list& load) std::list::iterator kit; for(kit = vitem->tlvkvs.pairs.begin(); kit != vitem->tlvkvs.pairs.end(); ++kit) - if (kit->key != mOwnGpgId.toStdString()) + if (kit->key != mOwnGpgId.toStdString()) PGPHandler::setAcceptConnexion(RsPgpId(kit->key), (kit->value == "TRUE")); } delete (*it); diff --git a/retroshare-nogui/src/TerminalApiClient.cpp b/retroshare-nogui/src/TerminalApiClient.cpp index a52d51567..81eebe6b4 100644 --- a/retroshare-nogui/src/TerminalApiClient.cpp +++ b/retroshare-nogui/src/TerminalApiClient.cpp @@ -96,6 +96,23 @@ TerminalApiClient::~TerminalApiClient() fullstop(); } +static std::string readStringFromKeyboard(bool passwd_mode) +{ + int c ; + std::string s; + + while((c=getchar()) != '\n') + { + if(passwd_mode) + putchar('*') ; + else + putchar(c) ; + + s += c ; + } + return s ; +} + void TerminalApiClient::data_tick() { // values in milliseconds @@ -109,6 +126,7 @@ void TerminalApiClient::data_tick() int last_char = 0; std::string inbuf; bool enter_was_pressed = false; + bool prev_is_bad = false ; int account_number_size = 1 ; int selected_account_number = 0 ; int account_number_typed = 0 ; @@ -178,45 +196,63 @@ void TerminalApiClient::data_tick() if(runstate_state_token.isNull()) { edge = true; - JsonStream reqs; - JsonStream resps; - Request req(reqs); - std::stringstream ss; - Response resp(resps, ss); - - req.mPath.push("runstate"); - req.mPath.push("control"); - reqs.switchToDeserialisation(); - - ApiServer::RequestId id = mApiServer->handleRequest(req, resp); - waitForResponse(id); - - resps.switchToDeserialisation(); - resps << makeKeyValueReference("runstate", runstate); - runstate_state_token = resp.mStateToken; - } + readRunState(runstate_state_token,runstate) ; + } if(password_state_token.isNull()) - { + { edge = true; - JsonStream reqs; - JsonStream resps; - Request req(reqs); - std::stringstream ss; - Response resp(resps, ss); + readPasswordState(password_state_token,ask_for_password,key_name,prev_is_bad) ; + } - req.mPath.push("password"); - req.mPath.push("control"); - reqs.switchToDeserialisation(); + if(!ask_for_password && edge && runstate == "waiting_account_select") + { + readAvailableAccounts(accounts) ; + account_number_size = (int)ceil(log(accounts.size())/log(10.0f)) ; - ApiServer::RequestId id = mApiServer->handleRequest(req, resp); - waitForResponse(id); + for(uint32_t i=0;i= accounts.size()) + { + std::cout << std::endl << "Type account number: " ; + std::cout.flush() ; + + std::string s = readStringFromKeyboard(false) ; + + if(sscanf(s.c_str(),"%d",&selected_account_number) != 1) + continue ; + + if(selected_account_number >= accounts.size()) + { + std::cerr << ": invalid account number (should be between " << std::setw(account_number_size) << std::setfill('0') + << 0 << " and " << std::setw(account_number_size) << std::setfill('0') << accounts.size()-1 << ")" << std::endl; + std::cout << std::endl << "Type account number: " ; + std::cout.flush() ; + + selected_account_number = accounts.size(); + } + + std::cout << std::endl << "Selected account: " << accounts[selected_account_number].name << " (" << accounts[selected_account_number].location << ") SSL id: " << accounts[selected_account_number].ssl_id << std::endl; + } + // now ask for passphrase + + std::string prompt = "Enter the password for key " + key_name + " : " ; + std::cout << prompt ; + std::cout.flush(); + std::string passwd = readStringFromKeyboard(true); + + // now we have passwd and account number, so send it to the core. + + std::string acc_ssl_id = accounts[selected_account_number].ssl_id.toStdString(); + + sendPassword(passwd) ; + sendSelectedAccount(acc_ssl_id) ; } +#ifdef OLD_CODE if(!ask_for_password && edge && runstate == "waiting_account_select") { readAvailableAccounts(accounts) ; @@ -278,9 +314,12 @@ void TerminalApiClient::data_tick() // Send passwd to api server sendPassword(inbuf) ; + usleep(1000*1000) ; + // clears buffer inbuf.clear(); } +#endif } } @@ -373,7 +412,7 @@ void TerminalApiClient::readAvailableAccounts(std::vector& accounts } -bool TerminalApiClient::isTokenValid(StateToken runstate_state_token) +bool TerminalApiClient::isTokenValid(StateToken runstate_state_token) const { JsonStream reqs; JsonStream resps; @@ -395,4 +434,50 @@ bool TerminalApiClient::isTokenValid(StateToken runstate_state_token) return true; } +void TerminalApiClient::readPasswordState(StateToken& password_state_token,bool& ask_for_password,std::string& key_name,bool& prev_is_bad) const +{ + JsonStream reqs; + JsonStream resps; + Request req(reqs); + std::stringstream ss; + Response resp(resps, ss); + + req.mPath.push("password"); + req.mPath.push("control"); + reqs.switchToDeserialisation(); + + ApiServer::RequestId id = mApiServer->handleRequest(req, resp); + waitForResponse(id); + + resps.switchToDeserialisation(); + resps << makeKeyValueReference("want_password", ask_for_password); + resps << makeKeyValueReference("key_name", key_name); + resps << makeKeyValueReference("prev_is_bad", prev_is_bad); + password_state_token = resp.mStateToken; + + std::cerr << "****** Passwd state changed: want_passwd=" << ask_for_password << " key_name=" << key_name << " prev_is_bad=" << prev_is_bad << std::endl; +} + +void TerminalApiClient::readRunState(StateToken& runstate_state_token,std::string& runstate) const +{ + JsonStream reqs; + JsonStream resps; + Request req(reqs); + std::stringstream ss; + Response resp(resps, ss); + + req.mPath.push("runstate"); + req.mPath.push("control"); + reqs.switchToDeserialisation(); + + ApiServer::RequestId id = mApiServer->handleRequest(req, resp); + waitForResponse(id); + + resps.switchToDeserialisation(); + resps << makeKeyValueReference("runstate", runstate); + runstate_state_token = resp.mStateToken; + + std::cerr << "****** Run State changed to \"" << runstate << "\"" << std::endl; +} + } // namespace resource_api diff --git a/retroshare-nogui/src/TerminalApiClient.h b/retroshare-nogui/src/TerminalApiClient.h index 4f72afb12..632438124 100644 --- a/retroshare-nogui/src/TerminalApiClient.h +++ b/retroshare-nogui/src/TerminalApiClient.h @@ -28,7 +28,7 @@ private: void waitForResponse(ApiServer::RequestId id) const; - bool isTokenValid(StateToken st); + bool isTokenValid(StateToken st) const; ApiServer* mApiServer; // Methods to talk to the ApiServer @@ -37,6 +37,8 @@ private: void sendSelectedAccount(const std::string& ssl_id) const; void readAvailableAccounts(std::vector& accounts) const; void getRunningState() const ; + void readPasswordState(StateToken& password_state_token,bool& ask_for_password,std::string& key_name,bool& prev_is_bad) const; + void readRunState(StateToken& runstate_state_token, std::__cxx11::string& runstate) const; }; } // namespace resource_api diff --git a/retroshare-nogui/src/retroshare.cc b/retroshare-nogui/src/retroshare.cc index 2e0b5d443..b0273da51 100644 --- a/retroshare-nogui/src/retroshare.cc +++ b/retroshare-nogui/src/retroshare.cc @@ -108,16 +108,16 @@ int main(int argc, char **argv) if(!tac.isRunning()) { - if(!RsInit::isLocationRunning()) - { - std::cerr << "Terminal API client stopped but location not set ! Relaunching." ; - tac.start(); - } - else if(RsInit::isLocationRunning()) - { - std::cerr << "Terminal API client running but location already set ! Stopping it." ; - tac.shutdown(); - } +// if(!RsInit::isLocationRunning()) +// { +// std::cerr << "Terminal API client stopped but location not set ! Relaunching." ; +// tac.start(); +// } +// else if(RsInit::isLocationRunning()) +// { +// std::cerr << "Terminal API client running but location already set ! Stopping it." ; +// tac.shutdown(); +// } } }