mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 03:53:44 +02:00
More control/ refactoring
This commit is contained in:
parent
e22fae2397
commit
edff13dcae
5 changed files with 84 additions and 96 deletions
|
@ -51,43 +51,20 @@ static void _CBipcResultHandler(void *arg,IpcConnection *ipcc,IpcConnection::Eve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeControlClient::NodeControlClient(const char *hp,void (*resultHandler)(void *,const char *),void *arg,const char *authToken)
|
NodeControlClient::NodeControlClient(const char *ep,const char *authToken,void (*resultHandler)(void *,const char *),void *arg)
|
||||||
throw() :
|
throw() :
|
||||||
_impl((void *)new _NodeControlClientImpl)
|
_impl((void *)new _NodeControlClientImpl)
|
||||||
{
|
{
|
||||||
_NodeControlClientImpl *impl = (_NodeControlClientImpl *)_impl;
|
_NodeControlClientImpl *impl = (_NodeControlClientImpl *)_impl;
|
||||||
impl->ipcc = (IpcConnection *)0;
|
impl->resultHandler = resultHandler;
|
||||||
|
impl->arg = arg;
|
||||||
if (!hp)
|
try {
|
||||||
hp = ZT_DEFAULTS.defaultHomePath.c_str();
|
impl->ipcc = new IpcConnection(ep,&_CBipcResultHandler,_impl);
|
||||||
|
impl->ipcc->printf("auth %s"ZT_EOL_S,authToken);
|
||||||
std::string at;
|
} catch ( ... ) {
|
||||||
if (authToken)
|
impl->ipcc = (IpcConnection *)0;
|
||||||
at = authToken;
|
impl->err = "failure connecting to running ZeroTier One service";
|
||||||
else if (!Utils::readFile(authTokenDefaultSystemPath(),at)) {
|
|
||||||
if (!Utils::readFile(authTokenDefaultUserPath(),at)) {
|
|
||||||
impl->err = "no authentication token specified and authtoken.secret not readable";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string myid;
|
|
||||||
if (Utils::readFile((std::string(hp) + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),myid)) {
|
|
||||||
std::string myaddr(myid.substr(0,myid.find(':')));
|
|
||||||
if (myaddr.length() != 10)
|
|
||||||
impl->err = "invalid address extracted from identity.public";
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
impl->resultHandler = resultHandler;
|
|
||||||
impl->arg = arg;
|
|
||||||
impl->ipcc = new IpcConnection((std::string(ZT_IPC_ENDPOINT_BASE) + myaddr).c_str(),&_CBipcResultHandler,_impl);
|
|
||||||
impl->ipcc->printf("auth %s"ZT_EOL_S,at.c_str());
|
|
||||||
} catch ( ... ) {
|
|
||||||
impl->ipcc = (IpcConnection *)0;
|
|
||||||
impl->err = "failure connecting to running ZeroTier One service";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else impl->err = "unable to read identity.public";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeControlClient::~NodeControlClient()
|
NodeControlClient::~NodeControlClient()
|
||||||
|
@ -153,17 +130,25 @@ const char *NodeControlClient::authTokenDefaultUserPath()
|
||||||
return dlp.c_str();
|
return dlp.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *NodeControlClient::authTokenDefaultSystemPath()
|
std::string NodeControlClient::getAuthToken(const char *path,bool generateIfNotFound)
|
||||||
{
|
{
|
||||||
static std::string dsp;
|
unsigned char randbuf[24];
|
||||||
static Mutex dsp_m;
|
std::string token;
|
||||||
|
|
||||||
Mutex::Lock _l(dsp_m);
|
if (Utils::readFile(path,token))
|
||||||
|
return Utils::trim(token);
|
||||||
|
else token = "";
|
||||||
|
|
||||||
if (!dsp.length())
|
if (generateIfNotFound) {
|
||||||
dsp = (ZT_DEFAULTS.defaultHomePath + ZT_PATH_SEPARATOR_S"authtoken.secret");
|
Utils::getSecureRandom(randbuf,sizeof(randbuf));
|
||||||
|
for(unsigned int i=0;i<sizeof(randbuf);++i)
|
||||||
|
token.push_back(("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")[(unsigned int)randbuf[i] % 62]);
|
||||||
|
if (!Utils::writeFile(path,token))
|
||||||
|
return std::string();
|
||||||
|
Utils::lockDownFile(path,false);
|
||||||
|
}
|
||||||
|
|
||||||
return dsp.c_str();
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -31,14 +31,16 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef __WINDOWS__
|
||||||
|
#define ZT_IPC_ENDPOINT_BASE "\\\\.\\pipe\\ZeroTierOne-"
|
||||||
|
#else
|
||||||
|
#define ZT_IPC_ENDPOINT_BASE "/tmp/.ZeroTierOne-"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client for controlling a local ZeroTier One node
|
* Client for controlling a local ZeroTier One node
|
||||||
*
|
|
||||||
* Windows note: be sure you call WSAStartup() before using this,
|
|
||||||
* otherwise it will be unable to open a local UDP socket to
|
|
||||||
* communicate with the service.
|
|
||||||
*/
|
*/
|
||||||
class NodeControlClient
|
class NodeControlClient
|
||||||
{
|
{
|
||||||
|
@ -48,12 +50,11 @@ public:
|
||||||
*
|
*
|
||||||
* Initialization may fail. Call error() to check.
|
* Initialization may fail. Call error() to check.
|
||||||
*
|
*
|
||||||
* @param hp Home path of ZeroTier One instance or NULL for default system home path
|
* @param ep Endpoint to connect to (OS-dependent)
|
||||||
* @param resultHandler Function to call when commands provide results
|
* @param resultHandler Function to call when commands provide results
|
||||||
* @param arg First argument to result handler
|
* @param arg First argument to result handler
|
||||||
* @param authToken Authentication token or NULL (default) to read from authtoken.secret in home path
|
|
||||||
*/
|
*/
|
||||||
NodeControlClient(const char *hp,void (*resultHandler)(void *,const char *),void *arg,const char *authToken = (const char *)0)
|
NodeControlClient(const char *ep,const char *authToken,void (*resultHandler)(void *,const char *),void *arg)
|
||||||
throw();
|
throw();
|
||||||
|
|
||||||
~NodeControlClient();
|
~NodeControlClient();
|
||||||
|
@ -89,14 +90,18 @@ public:
|
||||||
static inline std::vector<std::string> splitLine(const std::string &line) { return splitLine(line.c_str()); }
|
static inline std::vector<std::string> splitLine(const std::string &line) { return splitLine(line.c_str()); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Default path for current user's authtoken.secret
|
* @return Default path for current user's authtoken.secret or ~/.zeroTierOneAuthToken (location is platform-dependent)
|
||||||
*/
|
*/
|
||||||
static const char *authTokenDefaultUserPath();
|
static const char *authTokenDefaultUserPath();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Default path to system authtoken.secret
|
* Load (or generate) the authentication token
|
||||||
|
*
|
||||||
|
* @param path Full path to authtoken.secret
|
||||||
|
* @param generateIfNotFound If true, generate and save if not found or readable (requires appropriate privileges, returns empty on failure)
|
||||||
|
* @return Authentication token or empty string on failure
|
||||||
*/
|
*/
|
||||||
static const char *authTokenDefaultSystemPath();
|
static std::string getAuthToken(const char *path,bool generateIfNotFound);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// NodeControlClient is not copyable
|
// NodeControlClient is not copyable
|
||||||
|
|
|
@ -29,7 +29,9 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "../node/Constants.hpp"
|
||||||
#include "NodeControlService.hpp"
|
#include "NodeControlService.hpp"
|
||||||
|
#include "NodeControlClient.hpp"
|
||||||
#include "../node/Node.hpp"
|
#include "../node/Node.hpp"
|
||||||
#include "../node/Utils.hpp"
|
#include "../node/Utils.hpp"
|
||||||
|
|
||||||
|
@ -114,7 +116,7 @@ void NodeControlService::_doCommand(IpcConnection *ipcc,const char *commandLine)
|
||||||
ipcc->printf("200 help terminate [<reason>]"ZT_EOL_S);
|
ipcc->printf("200 help terminate [<reason>]"ZT_EOL_S);
|
||||||
ipcc->printf("200 help updatecheck"ZT_EOL_S);
|
ipcc->printf("200 help updatecheck"ZT_EOL_S);
|
||||||
} else if (cmd[0] == "auth") {
|
} else if (cmd[0] == "auth") {
|
||||||
if ((cmd.size() > 1)&&(_authToken == cmd[1])) {
|
if ((cmd.size() > 1)&&(_authToken.length() > 0)&&(_authToken == cmd[1])) {
|
||||||
Mutex::Lock _l(_connections_m);
|
Mutex::Lock _l(_connections_m);
|
||||||
_connections[ipcc] = true;
|
_connections[ipcc] = true;
|
||||||
ipcc->printf("200 auth OK"ZT_EOL_S);
|
ipcc->printf("200 auth OK"ZT_EOL_S);
|
||||||
|
@ -226,25 +228,4 @@ void NodeControlService::_doCommand(IpcConnection *ipcc,const char *commandLine)
|
||||||
ipcc->printf("."ZT_EOL_S); // blank line ends response
|
ipcc->printf("."ZT_EOL_S); // blank line ends response
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NodeControlService::readOrCreateAuthtoken(const char *path,bool generateIfNotFound)
|
|
||||||
{
|
|
||||||
unsigned char randbuf[24];
|
|
||||||
std::string token;
|
|
||||||
|
|
||||||
if (Utils::readFile(path,token))
|
|
||||||
return token;
|
|
||||||
else token = "";
|
|
||||||
|
|
||||||
if (generateIfNotFound) {
|
|
||||||
Utils::getSecureRandom(randbuf,sizeof(randbuf));
|
|
||||||
for(unsigned int i=0;i<sizeof(randbuf);++i)
|
|
||||||
token.push_back(("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")[(unsigned int)randbuf[i] % 62]);
|
|
||||||
if (!Utils::writeFile(path,token))
|
|
||||||
return std::string();
|
|
||||||
Utils::lockDownFile(path,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ZeroTier
|
} // namespace ZeroTier
|
||||||
|
|
|
@ -38,12 +38,6 @@
|
||||||
#include "../node/NonCopyable.hpp"
|
#include "../node/NonCopyable.hpp"
|
||||||
#include "../node/Thread.hpp"
|
#include "../node/Thread.hpp"
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
|
||||||
#define ZT_IPC_ENDPOINT_BASE "\\\\.\\pipe\\ZeroTierOne-"
|
|
||||||
#else
|
|
||||||
#define ZT_IPC_ENDPOINT_BASE "/tmp/.ZeroTierOne-"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
class Node;
|
class Node;
|
||||||
|
@ -65,19 +59,11 @@ public:
|
||||||
|
|
||||||
~NodeControlService();
|
~NodeControlService();
|
||||||
|
|
||||||
// Background thread waits for node to initialize, then creates IpcListener
|
// Background thread waits for node to initialize, then creates IpcListener and
|
||||||
|
// terminates. It also terminates on delete if it hasn't bootstrapped yet.
|
||||||
void threadMain()
|
void threadMain()
|
||||||
throw();
|
throw();
|
||||||
|
|
||||||
/**
|
|
||||||
* Load (or generate) the authentication token
|
|
||||||
*
|
|
||||||
* @param path Full path to authtoken.secret
|
|
||||||
* @param generateIfNotFound If true, generate and save if not found or readable
|
|
||||||
* @return Authentication token or empty string on failure
|
|
||||||
*/
|
|
||||||
static std::string readOrCreateAuthtoken(const char *path,bool generateIfNotFound);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void _CBcommandHandler(void *arg,IpcConnection *ipcc,IpcConnection::EventType event,const char *commandLine);
|
static void _CBcommandHandler(void *arg,IpcConnection *ipcc,IpcConnection::EventType event,const char *commandLine);
|
||||||
void _doCommand(IpcConnection *ipcc,const char *commandLine);
|
void _doCommand(IpcConnection *ipcc,const char *commandLine);
|
||||||
|
|
49
main.cpp
49
main.cpp
|
@ -114,9 +114,10 @@ static void printHelp(FILE *out,const char *cn)
|
||||||
static void _CBresultHandler(void *arg,const char *line)
|
static void _CBresultHandler(void *arg,const char *line)
|
||||||
{
|
{
|
||||||
if (line) {
|
if (line) {
|
||||||
if ((line[0] == '.')&&(line[1] == (char)0))
|
if ((line[0] == '.')&&(line[1] == (char)0)) {
|
||||||
|
fflush(stdout);
|
||||||
*((bool *)arg) = true;
|
*((bool *)arg) = true;
|
||||||
else fprintf(stdout,"%s"ZT_EOL_S,line);
|
} else fprintf(stdout,"%s"ZT_EOL_S,line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,19 +154,43 @@ static int main(const char *homeDir,int argc,char **argv)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!homeDir)
|
||||||
|
homeDir = ZT_DEFAULTS.defaultHomePath.c_str();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
std::string buf;
|
||||||
|
if (!Utils::readFile((std::string(homeDir) + ZT_PATH_SEPARATOR_S + "identity.public").c_str(),buf)) {
|
||||||
|
fprintf(stderr,"%s: fatal error: unable to read node address from identity.public in home path"ZT_EOL_S,argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
Identity id;
|
||||||
|
if (!id.fromString(buf)) {
|
||||||
|
fprintf(stderr,"%s: fatal error: unable to read node address from identity.public in home path"ZT_EOL_S,argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string authToken(NodeControlClient::getAuthToken((std::string(homeDir) + ZT_PATH_SEPARATOR_S + "authtoken.secret").c_str(),false));
|
||||||
|
if (!authToken.length())
|
||||||
|
authToken = NodeControlClient::getAuthToken(NodeControlClient::authTokenDefaultUserPath(),false);
|
||||||
|
if (!authToken.length()) {
|
||||||
|
fprintf(stderr,"%s: fatal error: unable to read authentication token from home path or user home"ZT_EOL_S,argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
volatile bool done = false;
|
volatile bool done = false;
|
||||||
NodeControlClient client(homeDir,&_CBresultHandler,(void *)&done);
|
NodeControlClient client((std::string(ZT_IPC_ENDPOINT_BASE) + id.address().toString()).c_str(),authToken.c_str(),&_CBresultHandler,(void *)&done);
|
||||||
const char *err = client.error();
|
const char *err = client.error();
|
||||||
if (err) {
|
if (err) {
|
||||||
fprintf(stderr,"%s: fatal error: unable to connect (is ZeroTier One running?) (%s)"ZT_EOL_S,argv[0],err);
|
fprintf(stderr,"%s: fatal error: unable to connect (is ZeroTier One running?) (%s)"ZT_EOL_S,argv[0],err);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
client.send(query.c_str());
|
client.send(query.c_str());
|
||||||
while (!done)
|
while (!done) Thread::sleep(100); // dis be ghetto
|
||||||
Thread::sleep(100); // ghetto
|
} catch (std::exception &exc) {
|
||||||
|
fprintf(stderr,"%s: fatal error: unable to connect (is ZeroTier One running?) (%s)"ZT_EOL_S,argv[0],exc.what());
|
||||||
|
return 1;
|
||||||
} catch ( ... ) {
|
} catch ( ... ) {
|
||||||
fprintf(stderr,"%s: fatal error: unable to connect (is ZeroTier One running?)"ZT_EOL_S,argv[0]);
|
fprintf(stderr,"%s: fatal error: unable to connect (is ZeroTier One running?) (unknown exception)"ZT_EOL_S,argv[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -758,12 +783,19 @@ int main(int argc,char **argv)
|
||||||
bool needsReset = false;
|
bool needsReset = false;
|
||||||
EthernetTapFactory *tapFactory = (EthernetTapFactory *)0;
|
EthernetTapFactory *tapFactory = (EthernetTapFactory *)0;
|
||||||
RoutingTable *routingTable = (RoutingTable *)0;
|
RoutingTable *routingTable = (RoutingTable *)0;
|
||||||
|
NodeControlService *controlService = (NodeControlService *)0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// Get or create authtoken.secret -- note that if this fails, authentication
|
||||||
|
// will always fail since an empty auth token won't work. This should always
|
||||||
|
// succeed unless something is wrong with the filesystem.
|
||||||
|
std::string authToken(NodeControlClient::getAuthToken((std::string(homeDir) + ZT_PATH_SEPARATOR_S + "authtoken.secret").c_str(),true));
|
||||||
|
|
||||||
tapFactory = ZTCreatePlatformEthernetTapFactory;
|
tapFactory = ZTCreatePlatformEthernetTapFactory;
|
||||||
routingTable = ZTCreatePlatformRoutingTable;
|
routingTable = ZTCreatePlatformRoutingTable;
|
||||||
|
|
||||||
node = new Node(homeDir,tapFactory,routingTable,udpPort,tcpPort,needsReset);
|
node = new Node(homeDir,tapFactory,routingTable,udpPort,tcpPort,needsReset);
|
||||||
|
controlService = new NodeControlService(node,authToken.c_str());
|
||||||
|
|
||||||
switch(node->run()) {
|
switch(node->run()) {
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
@ -807,9 +839,6 @@ int main(int argc,char **argv)
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete node;
|
|
||||||
node = (Node *)0;
|
|
||||||
} catch ( std::exception &exc ) {
|
} catch ( std::exception &exc ) {
|
||||||
fprintf(stderr,"%s: unexpected exception: %s"ZT_EOL_S,argv[0],exc.what());
|
fprintf(stderr,"%s: unexpected exception: %s"ZT_EOL_S,argv[0],exc.what());
|
||||||
exitCode = 3;
|
exitCode = 3;
|
||||||
|
@ -818,6 +847,8 @@ int main(int argc,char **argv)
|
||||||
exitCode = 3;
|
exitCode = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete controlService;
|
||||||
|
delete node; node = (Node *)0;
|
||||||
delete routingTable;
|
delete routingTable;
|
||||||
delete tapFactory;
|
delete tapFactory;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue