updated included zerotierone src

This commit is contained in:
Joseph Henry
2016-10-21 15:44:36 -07:00
parent 3dfea66bd4
commit 12bd9439db
105 changed files with 5083 additions and 6969 deletions

View File

@@ -48,12 +48,12 @@
#include <string>
#include <stdexcept>
#include <iostream>
#include <sstream>
#include "version.h"
#include "include/ZeroTierOne.h"
#include "ext/json-parser/json.h"
#include "node/Identity.hpp"
#include "node/CertificateOfMembership.hpp"
#include "node/Utils.hpp"
@@ -64,8 +64,6 @@
#include "service/OneService.hpp"
#include "ext/json/json.hpp"
#define ZT_PID_PATH "zerotier-one.pid"
using namespace ZeroTier;
@@ -84,8 +82,6 @@ static OneService *volatile zt1Service = (OneService *)0;
/* zerotier-cli personality */
/****************************************************************************/
// This is getting deprecated soon in favor of the stuff in cli/
static void cliPrintHelp(const char *pn,FILE *out)
{
fprintf(out,
@@ -95,21 +91,21 @@ static void cliPrintHelp(const char *pn,FILE *out)
fprintf(out,
COPYRIGHT_NOTICE ZT_EOL_S
LICENSE_GRANT ZT_EOL_S);
fprintf(out,"Usage: %s [-switches] <command/path> [<args>]" ZT_EOL_S"" ZT_EOL_S,pn);
fprintf(out,"Available switches:" ZT_EOL_S);
fprintf(out," -h - Display this help" ZT_EOL_S);
fprintf(out," -v - Show version" ZT_EOL_S);
fprintf(out," -j - Display full raw JSON output" ZT_EOL_S);
fprintf(out," -D<path> - ZeroTier home path for parameter auto-detect" ZT_EOL_S);
fprintf(out," -p<port> - HTTP port (default: auto)" ZT_EOL_S);
fprintf(out," -T<token> - Authentication token (default: auto)" ZT_EOL_S);
fprintf(out,ZT_EOL_S"Available commands:" ZT_EOL_S);
fprintf(out," info - Display status info" ZT_EOL_S);
fprintf(out," listpeers - List all peers" ZT_EOL_S);
fprintf(out," listnetworks - List all networks" ZT_EOL_S);
fprintf(out," join <network> - Join a network" ZT_EOL_S);
fprintf(out," leave <network> - Leave a network" ZT_EOL_S);
fprintf(out," set <network> <setting> - Set a network setting" ZT_EOL_S);
fprintf(out,"Usage: %s [-switches] <command/path> [<args>]"ZT_EOL_S""ZT_EOL_S,pn);
fprintf(out,"Available switches:"ZT_EOL_S);
fprintf(out," -h - Display this help"ZT_EOL_S);
fprintf(out," -v - Show version"ZT_EOL_S);
fprintf(out," -j - Display full raw JSON output"ZT_EOL_S);
fprintf(out," -D<path> - ZeroTier home path for parameter auto-detect"ZT_EOL_S);
fprintf(out," -p<port> - HTTP port (default: auto)"ZT_EOL_S);
fprintf(out," -T<token> - Authentication token (default: auto)"ZT_EOL_S);
//fprintf(out," -H<ip> - HTTP server bind address (default: 127.0.0.1)"ZT_EOL_S);
fprintf(out,ZT_EOL_S"Available commands:"ZT_EOL_S);
fprintf(out," info - Display status info"ZT_EOL_S);
fprintf(out," listpeers - List all peers"ZT_EOL_S);
fprintf(out," listnetworks - List all networks"ZT_EOL_S);
fprintf(out," join <network> - Join a network"ZT_EOL_S);
fprintf(out," leave <network> - Leave a network"ZT_EOL_S);
}
static std::string cliFixJsonCRs(const std::string &s)
@@ -130,7 +126,10 @@ static int cli(int argc,char **argv)
#endif
{
unsigned int port = 0;
std::string homeDir,command,arg1,arg2,authToken;
std::string homeDir;
std::string command;
std::string arg1;
std::string authToken;
std::string ip("127.0.0.1");
bool json = false;
for(int i=1;i<argc;++i) {
@@ -192,7 +191,7 @@ static int cli(int argc,char **argv)
cliPrintHelp(argv[0],stdout);
return 1;
}
printf("%d.%d.%d" ZT_EOL_S,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION);
printf("%d.%d.%d"ZT_EOL_S,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION);
return 0;
case 'h':
@@ -202,9 +201,7 @@ static int cli(int argc,char **argv)
return 0;
}
} else {
if (arg1.length())
arg2 = argv[i];
else if (command.length())
if (command.length())
arg1 = argv[i];
else command = argv[i];
}
@@ -214,7 +211,7 @@ static int cli(int argc,char **argv)
if ((!port)||(!authToken.length())) {
if (!homeDir.length()) {
fprintf(stderr,"%s: missing port or authentication token and no home directory specified to auto-detect" ZT_EOL_S,argv[0]);
fprintf(stderr,"%s: missing port or authentication token and no home directory specified to auto-detect"ZT_EOL_S,argv[0]);
return 2;
}
@@ -223,7 +220,7 @@ static int cli(int argc,char **argv)
OSUtils::readFile((homeDir + ZT_PATH_SEPARATOR_S + "zerotier-one.port").c_str(),portStr);
port = Utils::strToUInt(portStr.c_str());
if ((port == 0)||(port > 0xffff)) {
fprintf(stderr,"%s: missing port and zerotier-one.port not found in %s" ZT_EOL_S,argv[0],homeDir.c_str());
fprintf(stderr,"%s: missing port and zerotier-one.port not found in %s"ZT_EOL_S,argv[0],homeDir.c_str());
return 2;
}
}
@@ -245,7 +242,7 @@ static int cli(int argc,char **argv)
}
#endif
if (!authToken.length()) {
fprintf(stderr,"%s: missing authentication token and authtoken.secret not found (or readable) in %s" ZT_EOL_S,argv[0],homeDir.c_str());
fprintf(stderr,"%s: missing authentication token and authtoken.secret not found (or readable) in %s"ZT_EOL_S,argv[0],homeDir.c_str());
return 2;
}
}
@@ -277,143 +274,227 @@ static int cli(int argc,char **argv)
printf("%s",cliFixJsonCRs(responseBody).c_str());
return 0;
} else {
printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
printf("%u %s %s"ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
return 1;
}
} else if ((command == "info")||(command == "status")) {
const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/status",requestHeaders,responseHeaders,responseBody);
nlohmann::json j;
try {
j = nlohmann::json::parse(responseBody);
} catch (std::exception &exc) {
printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what());
return 1;
} catch ( ... ) {
printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str());
return 1;
}
unsigned int scode = Http::GET(
1024 * 1024 * 16,
60000,
(const struct sockaddr *)&addr,
"/status",
requestHeaders,
responseHeaders,
responseBody);
if (scode == 200) {
std::ostringstream out;
if (json) {
out << j.dump(2) << ZT_EOL_S;
printf("%s",cliFixJsonCRs(responseBody).c_str());
return 0;
} else {
if (j.is_object())
out << "200 info " << j["address"].get<std::string>() << " " << j["version"].get<std::string>() << " " << ((j["tcpFallbackActive"]) ? "TUNNELED" : ((j["online"]) ? "ONLINE" : "OFFLINE")) << ZT_EOL_S;
json_value *j = json_parse(responseBody.c_str(),responseBody.length());
bool good = false;
if (j) {
if (j->type == json_object) {
const char *address = (const char *)0;
bool online = false;
const char *version = (const char *)0;
for(unsigned int k=0;k<j->u.object.length;++k) {
if ((!strcmp(j->u.object.values[k].name,"address"))&&(j->u.object.values[k].value->type == json_string))
address = j->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(j->u.object.values[k].name,"version"))&&(j->u.object.values[k].value->type == json_string))
version = j->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(j->u.object.values[k].name,"online"))&&(j->u.object.values[k].value->type == json_boolean))
online = (j->u.object.values[k].value->u.boolean != 0);
}
if ((address)&&(version)) {
printf("200 info %s %s %s"ZT_EOL_S,address,(online ? "ONLINE" : "OFFLINE"),version);
good = true;
}
}
json_value_free(j);
}
if (good) {
return 0;
} else {
printf("%u %s invalid JSON response"ZT_EOL_S,scode,command.c_str());
return 1;
}
}
printf("%s",out.str().c_str());
return 0;
} else {
printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
printf("%u %s %s"ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
return 1;
}
} else if (command == "listpeers") {
const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/peer",requestHeaders,responseHeaders,responseBody);
nlohmann::json j;
try {
j = nlohmann::json::parse(responseBody);
} catch (std::exception &exc) {
printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what());
return 1;
} catch ( ... ) {
printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str());
return 1;
}
unsigned int scode = Http::GET(
1024 * 1024 * 16,
60000,
(const struct sockaddr *)&addr,
"/peer",
requestHeaders,
responseHeaders,
responseBody);
if (scode == 200) {
std::ostringstream out;
if (json) {
out << j.dump(2) << ZT_EOL_S;
printf("%s",cliFixJsonCRs(responseBody).c_str());
return 0;
} else {
out << "200 listpeers <ztaddr> <path> <latency> <version> <role>" << ZT_EOL_S;
if (j.is_array()) {
for(unsigned long k=0;k<j.size();++k) {
auto &p = j[k];
std::string bestPath;
auto paths = p["paths"];
if (paths.is_array()) {
for(unsigned long i=0;i<paths.size();++i) {
auto &path = paths[i];
if (path["preferred"]) {
char tmp[256];
std::string addr = path["address"];
const uint64_t now = OSUtils::now();
Utils::snprintf(tmp,sizeof(tmp),"%s;%llu;%llu",addr.c_str(),now - (uint64_t)path["lastSend"],now - (uint64_t)path["lastReceive"]);
bestPath = tmp;
break;
printf("200 listpeers <ztaddr> <paths> <latency> <version> <role>"ZT_EOL_S);
json_value *j = json_parse(responseBody.c_str(),responseBody.length());
if (j) {
if (j->type == json_array) {
for(unsigned int p=0;p<j->u.array.length;++p) {
json_value *jp = j->u.array.values[p];
if (jp->type == json_object) {
const char *address = (const char *)0;
std::string paths;
int64_t latency = 0;
int64_t versionMajor = -1,versionMinor = -1,versionRev = -1;
const char *role = (const char *)0;
for(unsigned int k=0;k<jp->u.object.length;++k) {
if ((!strcmp(jp->u.object.values[k].name,"address"))&&(jp->u.object.values[k].value->type == json_string))
address = jp->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(jp->u.object.values[k].name,"versionMajor"))&&(jp->u.object.values[k].value->type == json_integer))
versionMajor = jp->u.object.values[k].value->u.integer;
else if ((!strcmp(jp->u.object.values[k].name,"versionMinor"))&&(jp->u.object.values[k].value->type == json_integer))
versionMinor = jp->u.object.values[k].value->u.integer;
else if ((!strcmp(jp->u.object.values[k].name,"versionRev"))&&(jp->u.object.values[k].value->type == json_integer))
versionRev = jp->u.object.values[k].value->u.integer;
else if ((!strcmp(jp->u.object.values[k].name,"role"))&&(jp->u.object.values[k].value->type == json_string))
role = jp->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(jp->u.object.values[k].name,"latency"))&&(jp->u.object.values[k].value->type == json_integer))
latency = jp->u.object.values[k].value->u.integer;
else if ((!strcmp(jp->u.object.values[k].name,"paths"))&&(jp->u.object.values[k].value->type == json_array)) {
for(unsigned int pp=0;pp<jp->u.object.values[k].value->u.array.length;++pp) {
json_value *jpath = jp->u.object.values[k].value->u.array.values[pp];
if (jpath->type == json_object) {
const char *paddr = (const char *)0;
int64_t lastSend = 0;
int64_t lastReceive = 0;
bool preferred = false;
bool active = false;
for(unsigned int kk=0;kk<jpath->u.object.length;++kk) {
if ((!strcmp(jpath->u.object.values[kk].name,"address"))&&(jpath->u.object.values[kk].value->type == json_string))
paddr = jpath->u.object.values[kk].value->u.string.ptr;
else if ((!strcmp(jpath->u.object.values[kk].name,"lastSend"))&&(jpath->u.object.values[kk].value->type == json_integer))
lastSend = jpath->u.object.values[kk].value->u.integer;
else if ((!strcmp(jpath->u.object.values[kk].name,"lastReceive"))&&(jpath->u.object.values[kk].value->type == json_integer))
lastReceive = jpath->u.object.values[kk].value->u.integer;
else if ((!strcmp(jpath->u.object.values[kk].name,"preferred"))&&(jpath->u.object.values[kk].value->type == json_boolean))
preferred = (jpath->u.object.values[kk].value->u.boolean != 0);
else if ((!strcmp(jpath->u.object.values[kk].name,"active"))&&(jpath->u.object.values[kk].value->type == json_boolean))
active = (jpath->u.object.values[kk].value->u.boolean != 0);
}
if ((paddr)&&(active)) {
int64_t now = (int64_t)OSUtils::now();
if (lastSend > 0)
lastSend = now - lastSend;
if (lastReceive > 0)
lastReceive = now - lastReceive;
char pathtmp[256];
Utils::snprintf(pathtmp,sizeof(pathtmp),"%s;%lld;%lld;%s",
paddr,
lastSend,
lastReceive,
(preferred ? "preferred" : "active"));
if (paths.length())
paths.push_back(',');
paths.append(pathtmp);
}
}
}
}
}
if ((address)&&(role)) {
char verstr[64];
if ((versionMajor >= 0)&&(versionMinor >= 0)&&(versionRev >= 0))
Utils::snprintf(verstr,sizeof(verstr),"%lld.%lld.%lld",versionMajor,versionMinor,versionRev);
else {
verstr[0] = '-';
verstr[1] = (char)0;
}
printf("200 listpeers %s %s %lld %s %s"ZT_EOL_S,address,(paths.length()) ? paths.c_str() : "-",(long long)latency,verstr,role);
}
}
}
if (bestPath.length() == 0) bestPath = "-";
char ver[128];
int64_t vmaj = p["versionMajor"];
int64_t vmin = p["versionMinor"];
int64_t vrev = p["versionRev"];
if (vmaj >= 0) {
Utils::snprintf(ver,sizeof(ver),"%lld.%lld.%lld",vmaj,vmin,vrev);
} else {
ver[0] = '-';
ver[1] = (char)0;
}
out << "200 listpeers " << p["address"].get<std::string>() << " " << bestPath << " " << p["latency"] << " " << ver << " " << p["role"].get<std::string>() << ZT_EOL_S;
}
json_value_free(j);
}
return 0;
}
printf("%s",out.str().c_str());
return 0;
} else {
printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
printf("%u %s %s"ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
return 1;
}
} else if (command == "listnetworks") {
const unsigned int scode = Http::GET(1024 * 1024 * 16,60000,(const struct sockaddr *)&addr,"/network",requestHeaders,responseHeaders,responseBody);
nlohmann::json j;
try {
j = nlohmann::json::parse(responseBody);
} catch (std::exception &exc) {
printf("%u %s invalid JSON response (%s)" ZT_EOL_S,scode,command.c_str(),exc.what());
return 1;
} catch ( ... ) {
printf("%u %s invalid JSON response (unknown exception)" ZT_EOL_S,scode,command.c_str());
return 1;
}
unsigned int scode = Http::GET(
1024 * 1024 * 16,
60000,
(const struct sockaddr *)&addr,
"/network",
requestHeaders,
responseHeaders,
responseBody);
if (scode == 200) {
std::ostringstream out;
if (json) {
out << j.dump(2) << ZT_EOL_S;
printf("%s",cliFixJsonCRs(responseBody).c_str());
return 0;
} else {
out << "200 listnetworks <nwid> <name> <mac> <status> <type> <dev> <ZT assigned ips>" << ZT_EOL_S;
if (j.is_array()) {
for(unsigned long i=0;i<j.size();++i) {
auto &n = j[i];
if (n.is_object()) {
std::string aa;
auto &assignedAddresses = n["assignedAddresses"];
if (assignedAddresses.is_array()) {
for(unsigned long j=0;j<assignedAddresses.size();++j) {
auto &addr = assignedAddresses[j];
if (addr.is_string()) {
if (aa.length() > 0) aa.push_back(',');
aa.append(addr);
printf("200 listnetworks <nwid> <name> <mac> <status> <type> <dev> <ZT assigned ips>"ZT_EOL_S);
json_value *j = json_parse(responseBody.c_str(),responseBody.length());
if (j) {
if (j->type == json_array) {
for(unsigned int p=0;p<j->u.array.length;++p) {
json_value *jn = j->u.array.values[p];
if (jn->type == json_object) {
const char *nwid = (const char *)0;
const char *name = "";
const char *mac = (const char *)0;
const char *status = (const char *)0;
const char *type = (const char *)0;
const char *portDeviceName = "";
std::string ips;
for(unsigned int k=0;k<jn->u.object.length;++k) {
if ((!strcmp(jn->u.object.values[k].name,"nwid"))&&(jn->u.object.values[k].value->type == json_string))
nwid = jn->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(jn->u.object.values[k].name,"name"))&&(jn->u.object.values[k].value->type == json_string))
name = jn->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(jn->u.object.values[k].name,"mac"))&&(jn->u.object.values[k].value->type == json_string))
mac = jn->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(jn->u.object.values[k].name,"status"))&&(jn->u.object.values[k].value->type == json_string))
status = jn->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(jn->u.object.values[k].name,"type"))&&(jn->u.object.values[k].value->type == json_string))
type = jn->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(jn->u.object.values[k].name,"portDeviceName"))&&(jn->u.object.values[k].value->type == json_string))
portDeviceName = jn->u.object.values[k].value->u.string.ptr;
else if ((!strcmp(jn->u.object.values[k].name,"assignedAddresses"))&&(jn->u.object.values[k].value->type == json_array)) {
for(unsigned int a=0;a<jn->u.object.values[k].value->u.array.length;++a) {
json_value *aa = jn->u.object.values[k].value->u.array.values[a];
if (aa->type == json_string) {
if (ips.length())
ips.push_back(',');
ips.append(aa->u.string.ptr);
}
}
}
}
if ((nwid)&&(mac)&&(status)&&(type)) {
printf("200 listnetworks %s %s %s %s %s %s %s"ZT_EOL_S,
nwid,
(((name)&&(name[0])) ? name : "-"),
mac,
status,
type,
(((portDeviceName)&&(portDeviceName[0])) ? portDeviceName : "-"),
((ips.length() > 0) ? ips.c_str() : "-"));
}
}
if (aa.length() == 0) aa = "-";
std::string name = n["name"];
if (name.length() == 0) name = "-";
out << "200 listnetworks " << n["nwid"].get<std::string>() << " " << name << " " << n["mac"].get<std::string>() << " " << n["status"].get<std::string>() << " " << n["type"].get<std::string>() << " " << n["portDeviceName"].get<std::string>() << " " << aa << ZT_EOL_S;
}
}
json_value_free(j);
}
}
printf("%s",out.str().c_str());
return 0;
} else {
printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
printf("%u %s %s"ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
return 1;
}
} else if (command == "join") {
@@ -437,11 +518,11 @@ static int cli(int argc,char **argv)
if (json) {
printf("%s",cliFixJsonCRs(responseBody).c_str());
} else {
printf("200 join OK" ZT_EOL_S);
printf("200 join OK"ZT_EOL_S);
}
return 0;
} else {
printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
printf("%u %s %s"ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
return 1;
}
} else if (command == "leave") {
@@ -461,51 +542,13 @@ static int cli(int argc,char **argv)
if (json) {
printf("%s",cliFixJsonCRs(responseBody).c_str());
} else {
printf("200 leave OK" ZT_EOL_S);
printf("200 leave OK"ZT_EOL_S);
}
return 0;
} else {
printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
printf("%u %s %s"ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
return 1;
}
} else if (command == "set") {
if (arg1.length() != 16) {
cliPrintHelp(argv[0],stderr);
return 2;
}
std::size_t eqidx = arg2.find('=');
if (eqidx != std::string::npos) {
if ((arg2.substr(0,eqidx) == "allowManaged")||(arg2.substr(0,eqidx) == "allowGlobal")||(arg2.substr(0,eqidx) == "allowDefault")) {
char jsons[1024];
Utils::snprintf(jsons,sizeof(jsons),"{\"%s\":%s}",
arg2.substr(0,eqidx).c_str(),
(((arg2.substr(eqidx,2) == "=t")||(arg2.substr(eqidx,2) == "=1")) ? "true" : "false"));
char cl[128];
Utils::snprintf(cl,sizeof(cl),"%u",(unsigned int)strlen(jsons));
requestHeaders["Content-Type"] = "application/json";
requestHeaders["Content-Length"] = cl;
unsigned int scode = Http::POST(
1024 * 1024 * 16,
60000,
(const struct sockaddr *)&addr,
(std::string("/network/") + arg1).c_str(),
requestHeaders,
jsons,
strlen(jsons),
responseHeaders,
responseBody);
if (scode == 200) {
printf("%s",cliFixJsonCRs(responseBody).c_str());
return 0;
} else {
printf("%u %s %s" ZT_EOL_S,scode,command.c_str(),responseBody.c_str());
return 1;
}
}
} else {
cliPrintHelp(argv[0],stderr);
return 2;
}
} else {
cliPrintHelp(argv[0],stderr);
return 0;
@@ -527,13 +570,13 @@ static void idtoolPrintHelp(FILE *out,const char *pn)
fprintf(out,
COPYRIGHT_NOTICE ZT_EOL_S
LICENSE_GRANT ZT_EOL_S);
fprintf(out,"Usage: %s <command> [<args>]" ZT_EOL_S"" ZT_EOL_S"Commands:" ZT_EOL_S,pn);
fprintf(out," generate [<identity.secret>] [<identity.public>] [<vanity>]" ZT_EOL_S);
fprintf(out," validate <identity.secret/public>" ZT_EOL_S);
fprintf(out," getpublic <identity.secret>" ZT_EOL_S);
fprintf(out," sign <identity.secret> <file>" ZT_EOL_S);
fprintf(out," verify <identity.secret/public> <file> <signature>" ZT_EOL_S);
fprintf(out," mkcom <identity.secret> [<id,value,maxDelta> ...] (hexadecimal integers)" ZT_EOL_S);
fprintf(out,"Usage: %s <command> [<args>]"ZT_EOL_S""ZT_EOL_S"Commands:"ZT_EOL_S,pn);
fprintf(out," generate [<identity.secret>] [<identity.public>] [<vanity>]"ZT_EOL_S);
fprintf(out," validate <identity.secret/public>"ZT_EOL_S);
fprintf(out," getpublic <identity.secret>"ZT_EOL_S);
fprintf(out," sign <identity.secret> <file>"ZT_EOL_S);
fprintf(out," verify <identity.secret/public> <file> <signature>"ZT_EOL_S);
fprintf(out," mkcom <identity.secret> [<id,value,maxDelta> ...] (hexadecimal integers)"ZT_EOL_S);
}
static Identity getIdFromArg(char *arg)
@@ -589,15 +632,15 @@ static int idtool(int argc,char **argv)
std::string idser = id.toString(true);
if (argc >= 3) {
if (!OSUtils::writeFile(argv[2],idser)) {
fprintf(stderr,"Error writing to %s" ZT_EOL_S,argv[2]);
fprintf(stderr,"Error writing to %s"ZT_EOL_S,argv[2]);
return 1;
} else printf("%s written" ZT_EOL_S,argv[2]);
} else printf("%s written"ZT_EOL_S,argv[2]);
if (argc >= 4) {
idser = id.toString(false);
if (!OSUtils::writeFile(argv[3],idser)) {
fprintf(stderr,"Error writing to %s" ZT_EOL_S,argv[3]);
fprintf(stderr,"Error writing to %s"ZT_EOL_S,argv[3]);
return 1;
} else printf("%s written" ZT_EOL_S,argv[3]);
} else printf("%s written"ZT_EOL_S,argv[3]);
}
} else printf("%s",idser.c_str());
} else if (!strcmp(argv[1],"validate")) {
@@ -608,14 +651,14 @@ static int idtool(int argc,char **argv)
Identity id = getIdFromArg(argv[2]);
if (!id) {
fprintf(stderr,"Identity argument invalid or file unreadable: %s" ZT_EOL_S,argv[2]);
fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
return 1;
}
if (!id.locallyValidate()) {
fprintf(stderr,"%s FAILED validation." ZT_EOL_S,argv[2]);
fprintf(stderr,"%s FAILED validation."ZT_EOL_S,argv[2]);
return 1;
} else printf("%s is a valid identity" ZT_EOL_S,argv[2]);
} else printf("%s is a valid identity"ZT_EOL_S,argv[2]);
} else if (!strcmp(argv[1],"getpublic")) {
if (argc < 3) {
idtoolPrintHelp(stdout,argv[0]);
@@ -624,7 +667,7 @@ static int idtool(int argc,char **argv)
Identity id = getIdFromArg(argv[2]);
if (!id) {
fprintf(stderr,"Identity argument invalid or file unreadable: %s" ZT_EOL_S,argv[2]);
fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
return 1;
}
@@ -637,18 +680,18 @@ static int idtool(int argc,char **argv)
Identity id = getIdFromArg(argv[2]);
if (!id) {
fprintf(stderr,"Identity argument invalid or file unreadable: %s" ZT_EOL_S,argv[2]);
fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
return 1;
}
if (!id.hasPrivate()) {
fprintf(stderr,"%s does not contain a private key (must use private to sign)" ZT_EOL_S,argv[2]);
fprintf(stderr,"%s does not contain a private key (must use private to sign)"ZT_EOL_S,argv[2]);
return 1;
}
std::string inf;
if (!OSUtils::readFile(argv[3],inf)) {
fprintf(stderr,"%s is not readable" ZT_EOL_S,argv[3]);
fprintf(stderr,"%s is not readable"ZT_EOL_S,argv[3]);
return 1;
}
C25519::Signature signature = id.sign(inf.data(),(unsigned int)inf.length());
@@ -661,21 +704,21 @@ static int idtool(int argc,char **argv)
Identity id = getIdFromArg(argv[2]);
if (!id) {
fprintf(stderr,"Identity argument invalid or file unreadable: %s" ZT_EOL_S,argv[2]);
fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
return 1;
}
std::string inf;
if (!OSUtils::readFile(argv[3],inf)) {
fprintf(stderr,"%s is not readable" ZT_EOL_S,argv[3]);
fprintf(stderr,"%s is not readable"ZT_EOL_S,argv[3]);
return 1;
}
std::string signature(Utils::unhex(argv[4]));
if ((signature.length() > ZT_ADDRESS_LENGTH)&&(id.verify(inf.data(),(unsigned int)inf.length(),signature.data(),(unsigned int)signature.length()))) {
printf("%s signature valid" ZT_EOL_S,argv[3]);
printf("%s signature valid"ZT_EOL_S,argv[3]);
} else {
fprintf(stderr,"%s signature check FAILED" ZT_EOL_S,argv[3]);
fprintf(stderr,"%s signature check FAILED"ZT_EOL_S,argv[3]);
return 1;
}
} else if (!strcmp(argv[1],"mkcom")) {
@@ -686,7 +729,7 @@ static int idtool(int argc,char **argv)
Identity id = getIdFromArg(argv[2]);
if ((!id)||(!id.hasPrivate())) {
fprintf(stderr,"Identity argument invalid, does not include private key, or file unreadable: %s" ZT_EOL_S,argv[2]);
fprintf(stderr,"Identity argument invalid, does not include private key, or file unreadable: %s"ZT_EOL_S,argv[2]);
return 1;
}
@@ -701,7 +744,7 @@ static int idtool(int argc,char **argv)
}
}
if (!com.sign(id)) {
fprintf(stderr,"Signature of certificate of membership failed." ZT_EOL_S);
fprintf(stderr,"Signature of certificate of membership failed."ZT_EOL_S);
return 1;
}
@@ -895,27 +938,27 @@ static void printHelp(const char *cn,FILE *out)
LICENSE_GRANT ZT_EOL_S);
std::string updateUrl(OneService::autoUpdateUrl());
if (updateUrl.length())
fprintf(out,"Automatic updates enabled:" ZT_EOL_S" %s" ZT_EOL_S" (all updates are securely authenticated by 256-bit ECDSA signature)" ZT_EOL_S"" ZT_EOL_S,updateUrl.c_str());
fprintf(out,"Usage: %s [-switches] [home directory]" ZT_EOL_S"" ZT_EOL_S,cn);
fprintf(out,"Available switches:" ZT_EOL_S);
fprintf(out," -h - Display this help" ZT_EOL_S);
fprintf(out," -v - Show version" ZT_EOL_S);
fprintf(out," -U - Run as unprivileged user (skip privilege check)" ZT_EOL_S);
fprintf(out," -p<port> - Port for UDP and TCP/HTTP (default: 9993, 0 for random)" ZT_EOL_S);
fprintf(out,"Automatic updates enabled:"ZT_EOL_S" %s"ZT_EOL_S" (all updates are securely authenticated by 256-bit ECDSA signature)"ZT_EOL_S""ZT_EOL_S,updateUrl.c_str());
fprintf(out,"Usage: %s [-switches] [home directory]"ZT_EOL_S""ZT_EOL_S,cn);
fprintf(out,"Available switches:"ZT_EOL_S);
fprintf(out," -h - Display this help"ZT_EOL_S);
fprintf(out," -v - Show version"ZT_EOL_S);
fprintf(out," -U - Run as unprivileged user (skip privilege check)"ZT_EOL_S);
fprintf(out," -p<port> - Port for UDP and TCP/HTTP (default: 9993, 0 for random)"ZT_EOL_S);
#ifdef __UNIX_LIKE__
fprintf(out," -d - Fork and run as daemon (Unix-ish OSes)" ZT_EOL_S);
fprintf(out," -d - Fork and run as daemon (Unix-ish OSes)"ZT_EOL_S);
#endif // __UNIX_LIKE__
#ifdef __WINDOWS__
fprintf(out," -C - Run from command line instead of as service (Windows)" ZT_EOL_S);
fprintf(out," -I - Install Windows service (Windows)" ZT_EOL_S);
fprintf(out," -R - Uninstall Windows service (Windows)" ZT_EOL_S);
fprintf(out," -D - Remove all instances of Windows tap device (Windows)" ZT_EOL_S);
fprintf(out," -C - Run from command line instead of as service (Windows)"ZT_EOL_S);
fprintf(out," -I - Install Windows service (Windows)"ZT_EOL_S);
fprintf(out," -R - Uninstall Windows service (Windows)"ZT_EOL_S);
fprintf(out," -D - Remove all instances of Windows tap device (Windows)"ZT_EOL_S);
#endif // __WINDOWS__
fprintf(out," -i - Generate and manage identities (zerotier-idtool)" ZT_EOL_S);
fprintf(out," -q - Query API (zerotier-cli)" ZT_EOL_S);
fprintf(out," -i - Generate and manage identities (zerotier-idtool)"ZT_EOL_S);
fprintf(out," -q - Query API (zerotier-cli)"ZT_EOL_S);
}
#ifdef __WINDOWS__
@@ -993,7 +1036,7 @@ int main(int argc,char **argv)
break;
case 'v': // Display version
printf("%d.%d.%d" ZT_EOL_S,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION);
printf("%d.%d.%d"ZT_EOL_S,ZEROTIER_ONE_VERSION_MAJOR,ZEROTIER_ONE_VERSION_MINOR,ZEROTIER_ONE_VERSION_REVISION);
return 0;
case 'i': // Invoke idtool personality
@@ -1015,12 +1058,12 @@ int main(int argc,char **argv)
case 'I': { // Install this binary as a Windows service
if (IsCurrentUserLocalAdministrator() != TRUE) {
fprintf(stderr,"%s: must be run as a local administrator." ZT_EOL_S,argv[0]);
fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
return 1;
}
std::string ret(InstallService(ZT_SERVICE_NAME,ZT_SERVICE_DISPLAY_NAME,ZT_SERVICE_START_TYPE,ZT_SERVICE_DEPENDENCIES,ZT_SERVICE_ACCOUNT,ZT_SERVICE_PASSWORD));
if (ret.length()) {
fprintf(stderr,"%s: unable to install service: %s" ZT_EOL_S,argv[0],ret.c_str());
fprintf(stderr,"%s: unable to install service: %s"ZT_EOL_S,argv[0],ret.c_str());
return 3;
}
return 0;
@@ -1028,12 +1071,12 @@ int main(int argc,char **argv)
case 'R': { // Uninstall this binary as Windows service
if (IsCurrentUserLocalAdministrator() != TRUE) {
fprintf(stderr,"%s: must be run as a local administrator." ZT_EOL_S,argv[0]);
fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
return 1;
}
std::string ret(UninstallService(ZT_SERVICE_NAME));
if (ret.length()) {
fprintf(stderr,"%s: unable to uninstall service: %s" ZT_EOL_S,argv[0],ret.c_str());
fprintf(stderr,"%s: unable to uninstall service: %s"ZT_EOL_S,argv[0],ret.c_str());
return 3;
}
return 0;
@@ -1042,7 +1085,7 @@ int main(int argc,char **argv)
case 'D': {
std::string err = WindowsEthernetTap::destroyAllPersistentTapDevices();
if (err.length() > 0) {
fprintf(stderr,"%s: unable to uninstall one or more persistent tap devices: %s" ZT_EOL_S,argv[0],err.c_str());
fprintf(stderr,"%s: unable to uninstall one or more persistent tap devices: %s"ZT_EOL_S,argv[0],err.c_str());
return 3;
}
return 0;
@@ -1068,7 +1111,7 @@ int main(int argc,char **argv)
if (!homeDir.length())
homeDir = OneService::platformDefaultHomePath();
if (!homeDir.length()) {
fprintf(stderr,"%s: no home path specified and no platform default available" ZT_EOL_S,argv[0]);
fprintf(stderr,"%s: no home path specified and no platform default available"ZT_EOL_S,argv[0]);
return 1;
} else {
std::vector<std::string> hpsp(Utils::split(homeDir.c_str(),ZT_PATH_SEPARATOR_S,"",""));
@@ -1086,23 +1129,17 @@ int main(int argc,char **argv)
}
}
// This can be removed once the new controller code has been around for many versions
if (OSUtils::fileExists((homeDir + ZT_PATH_SEPARATOR_S + "controller.db").c_str(),true)) {
fprintf(stderr,"%s: FATAL: an old controller.db exists in %s -- see instructions in controller/README.md for how to migrate!" ZT_EOL_S,argv[0],homeDir.c_str());
return 1;
}
#ifdef __UNIX_LIKE__
#ifndef ZT_ONE_NO_ROOT_CHECK
if ((!skipRootCheck)&&(getuid() != 0)) {
fprintf(stderr,"%s: must be run as root (uid 0)" ZT_EOL_S,argv[0]);
fprintf(stderr,"%s: must be run as root (uid 0)"ZT_EOL_S,argv[0]);
return 1;
}
#endif // !ZT_ONE_NO_ROOT_CHECK
if (runAsDaemon) {
long p = (long)fork();
if (p < 0) {
fprintf(stderr,"%s: could not fork" ZT_EOL_S,argv[0]);
fprintf(stderr,"%s: could not fork"ZT_EOL_S,argv[0]);
return 1;
} else if (p > 0)
return 0; // forked
@@ -1119,7 +1156,7 @@ int main(int argc,char **argv)
// Running in "interactive" mode (mostly for debugging)
if (IsCurrentUserLocalAdministrator() != TRUE) {
if (!skipRootCheck) {
fprintf(stderr,"%s: must be run as a local administrator." ZT_EOL_S,argv[0]);
fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
return 1;
}
} else {
@@ -1134,7 +1171,7 @@ int main(int argc,char **argv)
if (CServiceBase::Run(zt1Service) == TRUE) {
return 0;
} else {
fprintf(stderr,"%s: unable to start service (try -h for help)" ZT_EOL_S,argv[0]);
fprintf(stderr,"%s: unable to start service (try -h for help)"ZT_EOL_S,argv[0]);
return 1;
}
}
@@ -1161,7 +1198,7 @@ int main(int argc,char **argv)
case OneService::ONE_NORMAL_TERMINATION:
break;
case OneService::ONE_UNRECOVERABLE_ERROR:
fprintf(stderr,"%s: fatal error: %s" ZT_EOL_S,argv[0],zt1Service->fatalErrorMessage().c_str());
fprintf(stderr,"%s: fatal error: %s"ZT_EOL_S,argv[0],zt1Service->fatalErrorMessage().c_str());
returnValue = 1;
break;
case OneService::ONE_IDENTITY_COLLISION: {