diff --git a/idtool.cpp b/idtool.cpp
deleted file mode 100644
index 0731e4c15..000000000
--- a/idtool.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * ZeroTier One - Global Peer to Peer Ethernet
- * Copyright (C) 2012-2013 ZeroTier Networks LLC
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- * --
- *
- * ZeroTier may be used and distributed under the terms of the GPLv3, which
- * are available at: http://www.gnu.org/licenses/gpl-3.0.html
- *
- * If you would like to embed ZeroTier into a commercial application or
- * redistribute it in a modified binary form, please contact ZeroTier Networks
- * LLC. Start here: http://www.zerotier.com/
- */
-
-#include
-#include
-#include
-#include
-#include
-
-#include "node/Identity.hpp"
-#include "node/Utils.hpp"
-#include "node/C25519.hpp"
-#include "node/SHA512.hpp"
-#include "node/Dictionary.hpp"
-
-using namespace ZeroTier;
-
-static void printHelp(char *pn)
-{
- std::cout << "Usage: " << pn << " []" << std::endl << std::endl;
- std::cout << "Commands:" << std::endl;
- std::cout << "\tgenerate [] []" << std::endl;
- std::cout << "\tvalidate " << std::endl;
- std::cout << "\tgetpublic " << std::endl;
- std::cout << "\tsign " << std::endl;
- std::cout << "\tverify " << std::endl;
- std::cout << "\tsignupdate " << std::endl;
-}
-
-static Identity getIdFromArg(char *arg)
-{
- Identity id;
- if ((strlen(arg) > 32)&&(arg[10] == ':')) { // identity is a literal on the command line
- if (id.fromString(arg))
- return id;
- } else { // identity is to be read from a file
- std::string idser;
- if (Utils::readFile(arg,idser)) {
- if (id.fromString(idser))
- return id;
- }
- }
- return Identity();
-}
-
-int main(int argc,char **argv)
-{
- if (argc < 2) {
- printHelp(argv[0]);
- return -1;
- }
-
- if (!strcmp(argv[1],"generate")) {
- Identity id;
- id.generate();
- std::string idser = id.toString(true);
- if (argc >= 3) {
- if (!Utils::writeFile(argv[2],idser)) {
- std::cerr << "Error writing to " << argv[2] << std::endl;
- return -1;
- } else std::cout << argv[2] << " written" << std::endl;
- if (argc >= 4) {
- idser = id.toString(false);
- if (!Utils::writeFile(argv[3],idser)) {
- std::cerr << "Error writing to " << argv[3] << std::endl;
- return -1;
- } else std::cout << argv[3] << " written" << std::endl;
- }
- } else std::cout << idser;
- } else if (!strcmp(argv[1],"validate")) {
- if (argc < 3) {
- printHelp(argv[0]);
- return -1;
- }
-
- Identity id = getIdFromArg(argv[2]);
- if (!id) {
- std::cerr << "Identity argument invalid or file unreadable: " << argv[2] << std::endl;
- return -1;
- }
-
- if (!id.locallyValidate()) {
- std::cerr << argv[2] << " FAILED validation." << std::endl;
- return -1;
- } else std::cout << argv[2] << " is a valid identity (full check performed)" << std::endl;
- } else if (!strcmp(argv[1],"getpublic")) {
- if (argc < 3) {
- printHelp(argv[0]);
- return -1;
- }
-
- Identity id = getIdFromArg(argv[2]);
- if (!id) {
- std::cerr << "Identity argument invalid or file unreadable: " << argv[2] << std::endl;
- return -1;
- }
-
- std::cout << id.toString(false);
- } else if (!strcmp(argv[1],"sign")) {
- if (argc < 4) {
- printHelp(argv[0]);
- return -1;
- }
-
- Identity id = getIdFromArg(argv[2]);
- if (!id) {
- std::cerr << "Identity argument invalid or file unreadable: " << argv[2] << std::endl;
- return -1;
- }
-
- if (!id.hasPrivate()) {
- std::cerr << argv[2] << " does not contain a private key (must use private to sign)" << std::endl;
- return -1;
- }
-
- std::string inf;
- if (!Utils::readFile(argv[3],inf)) {
- std::cerr << argv[3] << " is not readable" << std::endl;
- return -1;
- }
- C25519::Signature signature = id.sign(inf.data(),inf.length());
- std::cout << Utils::hex(signature.data,signature.size());
- } else if (!strcmp(argv[1],"verify")) {
- if (argc < 4) {
- printHelp(argv[0]);
- return -1;
- }
-
- Identity id = getIdFromArg(argv[2]);
- if (!id) {
- std::cerr << "Identity argument invalid or file unreadable: " << argv[2] << std::endl;
- return -1;
- }
-
- std::string inf;
- if (!Utils::readFile(argv[3],inf)) {
- std::cerr << argv[3] << " is not readable" << std::endl;
- return -1;
- }
-
- std::string signature(Utils::unhex(argv[4]));
- if ((signature.length() > ZT_ADDRESS_LENGTH)&&(id.verify(inf.data(),inf.length(),signature.data(),signature.length()))) {
- std::cout << argv[3] << " signature valid" << std::endl;
- } else {
- std::cerr << argv[3] << " signature check FAILED" << std::endl;
- return -1;
- }
- } else if (!strcmp(argv[1],"signupdate")) {
- Identity id = getIdFromArg(argv[2]);
- if (!id) {
- std::cerr << "Identity argument invalid or file unreadable: " << argv[2] << std::endl;
- return -1;
- }
-
- std::string update;
- if (!Utils::readFile(argv[3],update)) {
- std::cerr << argv[3] << " is not readable" << std::endl;
- return -1;
- }
-
- unsigned char sha512[64];
- SHA512::hash(sha512,update.data(),update.length());
-
- char *atLastSep = strrchr(argv[3],ZT_PATH_SEPARATOR);
- std::string nameAndSha((atLastSep) ? (atLastSep + 1) : argv[3]);
- std::cout << "Signing filename '" << nameAndSha << "' plus SHA-512 digest " << Utils::hex(sha512,64) << std::endl;
- nameAndSha.append((const char *)sha512,64);
- C25519::Signature signature(id.sign(nameAndSha.data(),nameAndSha.length()));
-
- Dictionary sig;
- sig["sha512"] = Utils::hex(sha512,64);
- sig["sha512_ed25519"] = Utils::hex(signature.data,signature.size());
- sig["signedBy"] = id.address().toString();
- std::cout << "-- .sig file contents:" << std::endl << sig.toString() << "--" << std::endl;
-
- std::string sigPath(argv[3]);
- sigPath.append(".sig");
- if (!Utils::writeFile(sigPath.c_str(),sig.toString())) {
- std::cerr << "Could not write " << sigPath << std::endl;
- return -1;
- }
- std::cout << "Wrote " << sigPath << std::endl;
- } else {
- printHelp(argv[0]);
- return -1;
- }
-
- return 0;
-}
diff --git a/main.cpp b/main.cpp
index b2d96628f..c97a909b5 100644
--- a/main.cpp
+++ b/main.cpp
@@ -54,6 +54,8 @@
#include "node/Utils.hpp"
#include "node/Node.hpp"
#include "node/Condition.hpp"
+#include "node/C25519.hpp"
+#include "node/Identity.hpp"
using namespace ZeroTier;
@@ -68,10 +70,11 @@ static void printHelp(const char *cn,FILE *out)
fprintf(out," -h - Display this help"ZT_EOL_S);
fprintf(out," -p - Bind to this port for network I/O"ZT_EOL_S);
fprintf(out," -c - Bind to this port for local control packets"ZT_EOL_S);
- fprintf(out," -q - Send a query to a running service (zerotier-cli)");
+ fprintf(out," -q - Send a query to a running service (zerotier-cli)"ZT_EOL_S);
+ fprintf(out," -i - Run idtool command (zerotier-idtool)"ZT_EOL_S);
}
-namespace ZeroTierCLI { // ----------------------------------------------------
+namespace ZeroTierCLI { // ---------------------------------------------------
static void printHelp(FILE *out,const char *exename)
{
@@ -196,7 +199,154 @@ static int main(int argc,char **argv)
return 0;
}
-} // namespace ZeroTierCLI ----------------------------------------------------
+} // namespace ZeroTierCLI ---------------------------------------------------
+
+namespace ZeroTierIdTool { // ------------------------------------------------
+
+static void printHelp(FILE *out,const char *pn)
+{
+ fprintf(out,"Usage: %s []"ZT_EOL_S""ZT_EOL_S"Commands:"ZT_EOL_S,pn);
+ fprintf(out," generate [] []"ZT_EOL_S);
+ fprintf(out," validate "ZT_EOL_S);
+ fprintf(out," getpublic "ZT_EOL_S);
+ fprintf(out," sign "ZT_EOL_S);
+ fprintf(out," verify "ZT_EOL_S);
+}
+
+static Identity getIdFromArg(char *arg)
+{
+ Identity id;
+ if ((strlen(arg) > 32)&&(arg[10] == ':')) { // identity is a literal on the command line
+ if (id.fromString(arg))
+ return id;
+ } else { // identity is to be read from a file
+ std::string idser;
+ if (Utils::readFile(arg,idser)) {
+ if (id.fromString(idser))
+ return id;
+ }
+ }
+ return Identity();
+}
+
+// Runs instead of rest of main() if process is called zerotier-idtool or if
+// -i is specified as an option.
+#ifdef __WINDOWS__
+static int main(int argc,_TCHAR* argv[])
+#else
+static int main(int argc,char **argv)
+#endif
+{
+ if (argc < 2) {
+ printHelp(stderr,argv[0]);
+ return -1;
+ }
+
+ if (!strcmp(argv[1],"generate")) {
+ Identity id;
+ id.generate();
+ std::string idser = id.toString(true);
+ if (argc >= 3) {
+ if (!Utils::writeFile(argv[2],idser)) {
+ fprintf(stderr,"Error writing to %s"ZT_EOL_S,argv[2]);
+ return -1;
+ } else printf("%s written"ZT_EOL_S,argv[2]);
+ if (argc >= 4) {
+ idser = id.toString(false);
+ if (!Utils::writeFile(argv[3],idser)) {
+ 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",idser.c_str());
+ } else if (!strcmp(argv[1],"validate")) {
+ if (argc < 3) {
+ printHelp(stderr,argv[0]);
+ return -1;
+ }
+
+ Identity id = getIdFromArg(argv[2]);
+ if (!id) {
+ 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]);
+ return -1;
+ } else printf("%s is a valid identity"ZT_EOL_S,argv[2]);
+ } else if (!strcmp(argv[1],"getpublic")) {
+ if (argc < 3) {
+ printHelp(stderr,argv[0]);
+ return -1;
+ }
+
+ Identity id = getIdFromArg(argv[2]);
+ if (!id) {
+ fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
+ return -1;
+ }
+
+ printf("%s",id.toString(false).c_str());
+ } else if (!strcmp(argv[1],"sign")) {
+ if (argc < 4) {
+ printHelp(stderr,argv[0]);
+ return -1;
+ }
+
+ Identity id = getIdFromArg(argv[2]);
+ if (!id) {
+ 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]);
+ return -1;
+ }
+
+ std::string inf;
+ if (!Utils::readFile(argv[3],inf)) {
+ fprintf(stderr,"%s is not readable"ZT_EOL_S,argv[3]);
+ return -1;
+ }
+ C25519::Signature signature = id.sign(inf.data(),inf.length());
+ printf("%s",Utils::hex(signature.data,signature.size()).c_str());
+ } else if (!strcmp(argv[1],"verify")) {
+ if (argc < 4) {
+ printHelp(stderr,argv[0]);
+ return -1;
+ }
+
+ Identity id = getIdFromArg(argv[2]);
+ if (!id) {
+ fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
+ return -1;
+ }
+
+ std::string inf;
+ if (!Utils::readFile(argv[3],inf)) {
+ 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(),inf.length(),signature.data(),signature.length()))) {
+ printf("%s signature valid"ZT_EOL_S,argv[3]);
+ } else {
+ fprintf(stderr,"%s signature check FAILED"ZT_EOL_S,argv[3]);
+ return -1;
+ }
+ } else {
+ printHelp(stderr,argv[0]);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+} // namespace ZeroTierIdTool ------------------------------------------------
#ifdef __UNIX_LIKE__
static void sighandlerQuit(int sig)
@@ -250,6 +400,8 @@ int main(int argc,char **argv)
if ((strstr(argv[0],"zerotier-cli"))||(strstr(argv[0],"ZEROTIER-CLI")))
return ZeroTierCLI::main(argc,argv);
+ if ((strstr(argv[0],"zerotier-idtool"))||(strstr(argv[0],"ZEROTIER-IDTOOL")))
+ return ZeroTierIdTool::main(argc,argv);
const char *homeDir = (const char *)0;
unsigned int port = 0;
@@ -276,6 +428,11 @@ int main(int argc,char **argv)
printHelp(argv[0],stderr);
return 0;
} else return ZeroTierCLI::main(argc,argv);
+ case 'i':
+ if (argv[i][2]) {
+ printHelp(argv[0],stderr);
+ return 0;
+ } else return ZeroTierIdTool::main(argc,argv);
case 'h':
case '?':
default:
diff --git a/make-linux.mk b/make-linux.mk
index a432d9127..d57bc5f48 100644
--- a/make-linux.mk
+++ b/make-linux.mk
@@ -27,6 +27,7 @@ one: $(OBJS)
$(CXX) $(CXXFLAGS) -o zerotier-one main.cpp $(OBJS) $(LIBS)
$(STRIP) zerotier-one
ln -sf zerotier-one zerotier-cli
+ ln -sf zerotier-one zerotier-idtool
selftest: $(OBJS)
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.cpp $(OBJS) $(LIBS)
diff --git a/make-mac.mk b/make-mac.mk
index f0f56810e..8b1d121b4 100644
--- a/make-mac.mk
+++ b/make-mac.mk
@@ -23,15 +23,12 @@ one: $(OBJS)
$(CXX) $(CXXFLAGS) -o zerotier-one main.cpp $(OBJS) $(LIBS)
$(STRIP) zerotier-one
ln -sf zerotier-one zerotier-cli
+ ln -sf zerotier-one zerotier-idtool
selftest: $(OBJS)
$(CXX) $(CXXFLAGS) -o zerotier-selftest selftest.cpp $(OBJS) $(LIBS)
$(STRIP) zerotier-selftest
-idtool: $(OBJS)
- $(CXX) $(CXXFLAGS) -o zerotier-idtool idtool.cpp $(OBJS) $(LIBS)
- $(STRIP) zerotier-idtool
-
install-mac-tap: FORCE
mkdir -p /Library/Application\ Support/ZeroTier/One
rm -rf /Library/Application\ Support/ZeroTier/One/tap.kext