2018-09-28 18:15:10 -04:00
|
|
|
/*
|
|
|
|
* RetroShare Service
|
2019-09-10 11:10:26 -04:00
|
|
|
* Copyright (C) 2016-2019 Gioacchino Mazzurco <gio@eigenlab.org>
|
2018-09-28 18:15:10 -04:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
|
|
* License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2019-12-18 11:57:20 -05:00
|
|
|
*
|
|
|
|
* SPDX-FileCopyrightText: Retroshare Team <contact@retroshare.cc>
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
2018-09-28 18:15:10 -04:00
|
|
|
*/
|
|
|
|
|
2018-11-04 18:19:45 -05:00
|
|
|
#include "util/stacktrace.h"
|
2019-08-29 17:15:46 -04:00
|
|
|
#include "util/argstream.h"
|
2019-09-05 17:54:48 -04:00
|
|
|
#include "util/rskbdinput.h"
|
2019-08-29 17:15:46 -04:00
|
|
|
#include "retroshare/rsinit.h"
|
2019-09-08 04:29:24 -04:00
|
|
|
|
|
|
|
#ifdef RS_JSONAPI
|
2019-11-17 16:01:49 -05:00
|
|
|
#include "retroshare/rsjsonapi.h"
|
|
|
|
|
|
|
|
#ifdef RS_WEBUI
|
|
|
|
#include "retroshare/rswebui.h"
|
2019-09-08 04:29:24 -04:00
|
|
|
#endif
|
2019-11-27 15:14:20 -05:00
|
|
|
#endif
|
2018-11-04 18:19:45 -05:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
static CrashStackTrace gCrashStackTrace;
|
2018-11-04 18:19:45 -05:00
|
|
|
|
2019-08-29 17:15:46 -04:00
|
|
|
#include <cmath>
|
2018-09-28 18:15:10 -04:00
|
|
|
#include <csignal>
|
2019-09-08 05:02:34 -04:00
|
|
|
#include <iomanip>
|
2019-09-08 05:36:41 -04:00
|
|
|
#include <atomic>
|
2019-08-27 15:54:17 -04:00
|
|
|
|
2018-10-05 16:29:49 -04:00
|
|
|
#ifdef __ANDROID__
|
|
|
|
# include <QAndroidService>
|
2019-08-27 15:54:17 -04:00
|
|
|
# include <QCoreApplication>
|
|
|
|
# include <QObject>
|
|
|
|
# include <QStringList>
|
|
|
|
|
|
|
|
# include "util/androiddebug.h"
|
2018-10-05 16:29:49 -04:00
|
|
|
#endif // def __ANDROID__
|
|
|
|
|
2018-09-28 18:15:10 -04:00
|
|
|
#include "retroshare/rsinit.h"
|
|
|
|
#include "retroshare/rsiface.h"
|
2019-09-10 11:10:26 -04:00
|
|
|
#include "util/rsdebug.h"
|
2018-09-28 18:15:10 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
2019-08-29 04:57:15 -04:00
|
|
|
class RsServiceNotify: public NotifyClient
|
2019-08-27 15:54:17 -04:00
|
|
|
{
|
|
|
|
public:
|
2019-09-10 11:10:26 -04:00
|
|
|
RsServiceNotify() = default;
|
|
|
|
virtual ~RsServiceNotify() = default;
|
2019-08-27 15:54:17 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
virtual bool askForPassword(
|
|
|
|
const std::string& title, const std::string& question,
|
|
|
|
bool /*prev_is_bad*/, std::string& password, bool& cancel )
|
2019-08-27 15:54:17 -04:00
|
|
|
{
|
2019-09-10 11:10:26 -04:00
|
|
|
std::string question1 = title +
|
|
|
|
"\nPlease enter your PGP password for key:\n " +
|
|
|
|
question + " :";
|
2019-09-05 17:54:48 -04:00
|
|
|
password = RsUtil::rs_getpass(question1.c_str()) ;
|
2019-08-27 15:54:17 -04:00
|
|
|
cancel = false ;
|
|
|
|
|
|
|
|
return !password.empty();
|
|
|
|
}
|
|
|
|
};
|
2019-09-10 11:10:26 -04:00
|
|
|
#endif // def RS_SERVICE_TERMINAL_LOGIN
|
|
|
|
|
|
|
|
#ifdef __ANDROID__
|
|
|
|
void signalHandler(int /*signal*/) { QCoreApplication::exit(0); }
|
|
|
|
#else
|
|
|
|
static std::atomic<bool> keepRunning(true);
|
|
|
|
static int receivedSignal = 0;
|
|
|
|
|
|
|
|
void signalHandler(int signal)
|
|
|
|
{
|
|
|
|
if(RsControl::instance()->isReady())
|
|
|
|
RsControl::instance()->rsGlobalShutDown();
|
|
|
|
receivedSignal = signal;
|
|
|
|
keepRunning = false;
|
|
|
|
}
|
|
|
|
#endif // def __ANDROID__
|
2019-08-27 15:54:17 -04:00
|
|
|
|
|
|
|
|
2018-09-28 18:15:10 -04:00
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
#ifdef __ANDROID__
|
|
|
|
AndroidStdIOCatcher dbg; (void) dbg;
|
2018-10-05 16:29:49 -04:00
|
|
|
QAndroidService app(argc, argv);
|
2019-09-10 11:10:26 -04:00
|
|
|
#endif // def __ANDROID__
|
2018-09-28 18:15:10 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
signal(SIGINT, signalHandler);
|
|
|
|
signal(SIGTERM, signalHandler);
|
2018-09-28 18:15:10 -04:00
|
|
|
#ifdef SIGBREAK
|
2019-09-10 11:10:26 -04:00
|
|
|
signal(SIGBREAK, signalHandler);
|
2018-09-28 18:15:10 -04:00
|
|
|
#endif // ifdef SIGBREAK
|
|
|
|
|
2019-09-12 06:02:24 -04:00
|
|
|
RsInfo() << "\n" <<
|
2019-09-10 11:10:26 -04:00
|
|
|
"+================================================================+\n"
|
|
|
|
"| o---o o |\n"
|
2019-10-23 04:24:21 -04:00
|
|
|
"| \\ / - Retroshare Service - / \\ |\n"
|
2019-09-10 11:10:26 -04:00
|
|
|
"| o o---o |\n"
|
|
|
|
"+================================================================+"
|
|
|
|
<< std::endl << std::endl;
|
2019-08-27 15:54:17 -04:00
|
|
|
|
2018-09-28 18:15:10 -04:00
|
|
|
RsInit::InitRsConfig();
|
2019-08-27 15:54:17 -04:00
|
|
|
RsControl::earlyInitNotificationSystem();
|
2018-09-28 18:15:10 -04:00
|
|
|
|
2019-08-29 17:15:46 -04:00
|
|
|
#ifdef __APPLE__
|
|
|
|
// TODO: is this still needed with argstream?
|
|
|
|
/* HACK to avoid stupid OSX Finder behaviour
|
2019-09-10 11:10:26 -04:00
|
|
|
* remove the commandline arguments - if we detect we are launched from
|
|
|
|
* Finder, and we have the unparsable "-psn_0_12332" option.
|
2019-08-29 17:15:46 -04:00
|
|
|
* this is okay, as you cannot pass commandline arguments via Finder anyway
|
|
|
|
*/
|
|
|
|
if ((argc >= 2) && (0 == strncmp(argv[1], "-psn", 4))) argc = 1;
|
|
|
|
#endif
|
2019-08-29 04:57:15 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
std::string prefUserString;
|
|
|
|
RsConfigOptions conf;
|
2019-08-29 17:15:46 -04:00
|
|
|
|
2019-09-15 11:23:48 -04:00
|
|
|
#ifdef RS_JSONAPI
|
2019-11-27 12:44:10 -05:00
|
|
|
conf.jsonApiPort = RsJsonApi::DEFAULT_PORT; // enable JSonAPI by default
|
2019-11-27 15:14:20 -05:00
|
|
|
#ifdef RS_WEBUI
|
|
|
|
std::string webui_base_directory = RsWebUi::DEFAULT_BASE_DIRECTORY;
|
|
|
|
#endif
|
2019-09-15 11:23:48 -04:00
|
|
|
#endif
|
2019-09-15 10:21:12 -04:00
|
|
|
|
2019-08-29 17:15:46 -04:00
|
|
|
argstream as(argc,argv);
|
2019-09-10 11:10:26 -04:00
|
|
|
as >> option( 's', "stderr", conf.outStderr,
|
|
|
|
"output to stderr instead of log file." )
|
|
|
|
>> option( 'u',"udp", conf.udpListenerOnly,
|
|
|
|
"Only listen to UDP." )
|
|
|
|
>> parameter( 'c',"base-dir", conf.optBaseDir, "directory",
|
|
|
|
"Set base directory.", false )
|
|
|
|
>> parameter( 'l', "log-file", conf.logfname, "logfile",
|
|
|
|
"Set Log filename.", false )
|
|
|
|
>> parameter( 'd', "debug-level", conf.debugLevel, "level",
|
|
|
|
"Set debug level.", false )
|
|
|
|
>> parameter( 'i', "ip-address", conf.forcedInetAddress, "IP",
|
|
|
|
"Force IP address to use (if cannot be detected).", false )
|
|
|
|
>> parameter( 'o', "opmode", conf.opModeStr, "opmode",
|
|
|
|
"Set Operating mode (Full, NoTurtle, Gaming, Minimal).",
|
|
|
|
false )
|
|
|
|
>> parameter( 'p', "port", conf.forcedPort, "port",
|
|
|
|
"Set listenning port to use.", false );
|
|
|
|
|
|
|
|
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
|
|
|
as >> parameter( 'U', "user-id", prefUserString, "ID",
|
|
|
|
"[node Id] Selected account to use and asks for passphrase"
|
|
|
|
". Use \"-U list\" in order to list available accounts.",
|
|
|
|
false );
|
2019-11-27 12:44:10 -05:00
|
|
|
#endif // def RS_SERVICE_TERMINAL_LOGIN
|
2019-08-29 17:15:46 -04:00
|
|
|
|
|
|
|
#ifdef RS_JSONAPI
|
2019-09-10 11:10:26 -04:00
|
|
|
as >> parameter( 'J', "jsonApiPort", conf.jsonApiPort, "TCP Port",
|
|
|
|
"Enable JSON API on the specified port", false )
|
|
|
|
>> parameter( 'P', "jsonApiBindAddress", conf.jsonApiBindAddress,
|
|
|
|
"TCP bind address", "JSON API Bind Address default "
|
|
|
|
"127.0.0.1.", false );
|
2019-11-27 12:44:10 -05:00
|
|
|
#endif // def RS_JSONAPI
|
2019-09-10 11:10:26 -04:00
|
|
|
|
2019-11-27 15:14:20 -05:00
|
|
|
#if (defined(RS_JSONAPI) && defined(RS_WEBUI)) && defined(RS_SERVICE_TERMINAL_WEBUI_PASSWORD)
|
2019-09-10 11:10:26 -04:00
|
|
|
bool askWebUiPassword = false;
|
2019-11-17 16:01:49 -05:00
|
|
|
as >> parameter( 'B', "webui-directory", webui_base_directory, "Place where to find the html/js files for the webui.",false );
|
|
|
|
as >> option( 'W', "webui-password", askWebUiPassword, "Ask WebUI password on the console." );
|
2019-09-10 11:10:26 -04:00
|
|
|
#endif /* defined(RS_JSONAPI) && defined(RS_WEBUI) \
|
|
|
|
&& defined(RS_SERVICE_TERMINAL_WEBUI_PASSWORD) */
|
|
|
|
|
2019-08-29 17:15:46 -04:00
|
|
|
|
|
|
|
#ifdef LOCALNET_TESTING
|
2019-09-10 11:10:26 -04:00
|
|
|
as >> parameter( 'R', "restrict-port" , portRestrictions, "port1-port2",
|
|
|
|
"Apply port restriction", false);
|
2019-11-17 16:01:49 -05:00
|
|
|
#endif
|
2019-08-29 17:15:46 -04:00
|
|
|
|
|
|
|
#ifdef RS_AUTOLOGIN
|
2019-09-10 11:10:26 -04:00
|
|
|
as >> option( 'a', "auto-login", conf.autoLogin,
|
|
|
|
"enable auto-login." );
|
2019-11-17 16:01:49 -05:00
|
|
|
#endif
|
2019-08-29 17:15:46 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
as >> help( 'h', "help", "Display this Help" );
|
|
|
|
as.defaultErrorHandling(true, true);
|
2019-08-29 17:15:46 -04:00
|
|
|
|
2019-11-27 15:14:20 -05:00
|
|
|
#if (defined(RS_JSONAPI) && defined(RS_WEBUI)) && defined(RS_SERVICE_TERMINAL_WEBUI_PASSWORD)
|
2019-08-30 15:16:00 -04:00
|
|
|
std::string webui_pass1 = "Y";
|
2019-09-10 11:10:26 -04:00
|
|
|
if(askWebUiPassword)
|
2019-08-30 15:16:00 -04:00
|
|
|
{
|
2019-09-02 16:13:12 -04:00
|
|
|
std::string webui_pass2 = "N";
|
2019-08-30 15:16:00 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
while(keepRunning)
|
2019-08-30 15:16:00 -04:00
|
|
|
{
|
2019-09-10 11:10:26 -04:00
|
|
|
webui_pass1 = RsUtil::rs_getpass(
|
|
|
|
"Please register a password for the web interface: " );
|
|
|
|
webui_pass2 = RsUtil::rs_getpass(
|
|
|
|
"Please enter the same password again : " );
|
2019-09-02 16:13:12 -04:00
|
|
|
|
|
|
|
if(webui_pass1 != webui_pass2)
|
|
|
|
{
|
2019-09-10 11:10:26 -04:00
|
|
|
std::cout << "Passwords do not match!" << std::endl;
|
2019-09-02 16:13:12 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if(webui_pass1.empty())
|
|
|
|
{
|
2019-09-10 11:10:26 -04:00
|
|
|
std::cout << "Password cannot be empty!" << std::endl;
|
2019-09-02 16:13:12 -04:00
|
|
|
continue;
|
|
|
|
}
|
2019-08-30 15:16:00 -04:00
|
|
|
|
2019-09-02 16:13:12 -04:00
|
|
|
break;
|
|
|
|
}
|
2019-08-30 15:16:00 -04:00
|
|
|
}
|
2019-09-10 11:10:26 -04:00
|
|
|
#endif /* defined(RS_JSONAPI) && defined(RS_WEBUI)
|
|
|
|
&& defined(RS_SERVICE_TERMINAL_WEBUI_PASSWORD) */
|
2019-08-29 04:57:15 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
conf.main_executable_path = argv[0];
|
2019-08-29 17:15:46 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
int initResult = RsInit::InitRetroShare(conf);
|
|
|
|
if(initResult != RS_INIT_OK)
|
|
|
|
{
|
|
|
|
RsErr() << "Retroshare core initalization failed with: " << initResult
|
|
|
|
<< std::endl;
|
|
|
|
return -initResult;
|
|
|
|
}
|
2019-08-29 04:57:15 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
#ifdef RS_SERVICE_TERMINAL_LOGIN
|
|
|
|
if(!prefUserString.empty()) // Login from terminal requested
|
2019-08-29 17:15:46 -04:00
|
|
|
{
|
|
|
|
if(prefUserString == "list")
|
|
|
|
{
|
2019-09-10 11:10:26 -04:00
|
|
|
std::cout << std::endl << std::endl
|
|
|
|
<< "Available accounts:" << std::endl;
|
|
|
|
|
|
|
|
std::vector<RsLoginHelper::Location> locations;
|
|
|
|
rsLoginHelper->getLocations(locations);
|
|
|
|
|
|
|
|
int accountCountDigits = static_cast<int>(
|
|
|
|
ceil(log(locations.size())/log(10.0)) );
|
|
|
|
|
|
|
|
for( uint32_t i=0; i<locations.size(); ++i )
|
|
|
|
std::cout << "[" << std::setw(accountCountDigits)
|
|
|
|
<< std::setfill('0') << i+1 << "] "
|
|
|
|
<< locations[i].mLocationId << " ("
|
|
|
|
<< locations[i].mPgpId << "): "
|
|
|
|
<< locations[i].mPgpName
|
|
|
|
<< " \t (" << locations[i].mLocationName << ")"
|
|
|
|
<< std::endl;
|
|
|
|
|
|
|
|
uint32_t nacc = 0;
|
|
|
|
while(keepRunning && (nacc < 1 || nacc >= locations.size()))
|
2019-08-29 17:15:46 -04:00
|
|
|
{
|
|
|
|
std::cout << "Please enter account number: ";
|
|
|
|
std::cout.flush();
|
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
std::string inputStr;
|
|
|
|
std::getline(std::cin, inputStr);
|
2019-08-29 17:15:46 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
nacc = static_cast<uint32_t>(atoi(inputStr.c_str())-1);
|
|
|
|
if(nacc < locations.size())
|
2019-08-29 17:15:46 -04:00
|
|
|
{
|
|
|
|
prefUserString = locations[nacc].mLocationId.toStdString();
|
|
|
|
break;
|
|
|
|
}
|
2019-09-10 11:10:26 -04:00
|
|
|
nacc=0; // allow to continue if something goes wrong.
|
2019-08-29 17:15:46 -04:00
|
|
|
}
|
2019-09-10 11:10:26 -04:00
|
|
|
}
|
2019-08-29 17:15:46 -04:00
|
|
|
|
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
RsPeerId ssl_id(prefUserString);
|
2019-08-29 17:15:46 -04:00
|
|
|
if(ssl_id.isNull())
|
|
|
|
{
|
2019-09-10 11:10:26 -04:00
|
|
|
RsErr() << "Invalid User location id: a hexadecimal ID is expected."
|
|
|
|
<< std::endl;
|
|
|
|
return -EINVAL;
|
2019-08-29 17:15:46 -04:00
|
|
|
}
|
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
RsServiceNotify* notify = new RsServiceNotify();
|
2019-09-02 16:13:12 -04:00
|
|
|
rsNotify->registerNotifyClient(notify);
|
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
// supply empty passwd so that it is properly asked 3 times on console
|
2019-11-17 16:01:49 -05:00
|
|
|
RsInit::LoadCertificateStatus result = rsLoginHelper->attemptLogin(ssl_id, "");
|
2019-09-10 11:10:26 -04:00
|
|
|
|
|
|
|
switch(result)
|
|
|
|
{
|
|
|
|
case RsInit::OK: break;
|
|
|
|
case RsInit::ERR_ALREADY_RUNNING:
|
|
|
|
RsErr() << "Another RetroShare using the same profile is already "
|
|
|
|
"running on your system. Please close that instance "
|
|
|
|
"first." << std::endl << "Lock file: "
|
|
|
|
<< RsInit::lockFilePath() << std::endl;
|
|
|
|
return -RsInit::ERR_ALREADY_RUNNING;
|
|
|
|
case RsInit::ERR_CANT_ACQUIRE_LOCK:
|
|
|
|
RsErr() << "An unexpected error occurred when Retroshare tried to "
|
|
|
|
"acquire the single instance lock file." << std::endl
|
|
|
|
<< "Lock file: " << RsInit::lockFilePath() << std::endl;
|
|
|
|
return -RsInit::ERR_CANT_ACQUIRE_LOCK;
|
|
|
|
case RsInit::ERR_UNKNOWN: // Fall-throug
|
|
|
|
default:
|
|
|
|
RsErr() << "Cannot login. Check your passphrase." << std::endl
|
|
|
|
<< std::endl;
|
|
|
|
return -result;
|
2019-08-29 17:15:46 -04:00
|
|
|
}
|
|
|
|
}
|
2019-09-10 11:10:26 -04:00
|
|
|
#endif // def RS_SERVICE_TERMINAL_LOGIN
|
|
|
|
|
2019-11-27 15:14:20 -05:00
|
|
|
#if (defined(RS_JSONAPI) && defined(RS_WEBUI)) && defined(RS_SERVICE_TERMINAL_WEBUI_PASSWORD)
|
2019-11-30 17:12:32 -05:00
|
|
|
if(rsJsonApi && !webui_pass1.empty())
|
2019-11-17 16:01:49 -05:00
|
|
|
{
|
2019-11-30 17:12:32 -05:00
|
|
|
rsWebUi->setHtmlFilesDirectory(webui_base_directory);
|
|
|
|
rsWebUi->setUserPassword(webui_pass1);
|
|
|
|
rsWebUi->restart();
|
2019-11-17 16:01:49 -05:00
|
|
|
}
|
|
|
|
#endif
|
2019-08-29 17:15:46 -04:00
|
|
|
|
2019-08-27 15:54:17 -04:00
|
|
|
#ifdef __ANDROID__
|
2018-09-28 18:15:10 -04:00
|
|
|
rsControl->setShutdownCallback(QCoreApplication::exit);
|
2019-08-27 15:54:17 -04:00
|
|
|
|
2018-09-28 18:15:10 -04:00
|
|
|
QObject::connect(
|
|
|
|
&app, &QCoreApplication::aboutToQuit,
|
|
|
|
[](){
|
|
|
|
if(RsControl::instance()->isReady())
|
|
|
|
RsControl::instance()->rsGlobalShutDown(); } );
|
|
|
|
|
|
|
|
return app.exec();
|
2019-09-10 11:10:26 -04:00
|
|
|
#else // def __ANDROID__
|
2019-08-30 16:09:47 -04:00
|
|
|
rsControl->setShutdownCallback([&](int){keepRunning = false;});
|
|
|
|
|
|
|
|
while(keepRunning)
|
2019-09-10 11:10:26 -04:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
2019-08-27 15:54:17 -04:00
|
|
|
|
2019-09-10 11:10:26 -04:00
|
|
|
return 0;
|
|
|
|
#endif
|
2018-09-28 18:15:10 -04:00
|
|
|
}
|