fixed Terminal Api Client logic

This commit is contained in:
csoler 2017-07-09 21:16:41 +02:00
parent decbd3514d
commit 5dfbce7e3a
5 changed files with 208 additions and 80 deletions

View File

@ -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)

View File

@ -639,12 +639,12 @@ int AuthGPG::privateTrustCertificate(const RsPgpId& id, int trustlvl)
{
RsStackMutex stack(gpgMtxData); /******* LOCKED ******/
/* The certificate should be in Peers list ??? */
// 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))
{
std::cerr << "Invalid Certificate" << std::endl;
return 0;
}
int res = PGPHandler::privateTrustCertificate(id,trustlvl) ;
_force_sync_database = true ;

View File

@ -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();++i)
std::cout << "[" << std::setw(account_number_size) << std::setfill('0') << i << "] " << accounts[i].name << " (" << accounts[i].location << ")" << std::endl;
resps.switchToDeserialisation();
resps << makeKeyValueReference("want_password", ask_for_password);
resps << makeKeyValueReference("key_name", key_name);
password_state_token = resp.mStateToken;
selected_account_number = accounts.size() ;
account_number_typed = 0 ;
while(selected_account_number >= 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<AccountInfo>& 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

View File

@ -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<AccountInfo>& 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

View File

@ -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();
// }
}
}