main.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. /*
  2. * ZeroTier One - Global Peer to Peer Ethernet
  3. * Copyright (C) 2012-2013 ZeroTier Networks LLC
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. * --
  19. *
  20. * ZeroTier may be used and distributed under the terms of the GPLv3, which
  21. * are available at: http://www.gnu.org/licenses/gpl-3.0.html
  22. *
  23. * If you would like to embed ZeroTier into a commercial application or
  24. * redistribute it in a modified binary form, please contact ZeroTier Networks
  25. * LLC. Start here: http://www.zerotier.com/
  26. */
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <time.h>
  31. #include <errno.h>
  32. #include <string>
  33. #include <stdexcept>
  34. #include "node/Constants.hpp"
  35. #ifdef __WINDOWS__
  36. #include <WinSock2.h>
  37. #include <Windows.h>
  38. #include <tchar.h>
  39. #include <wchar.h>
  40. #include <lmcons.h>
  41. #else
  42. #include <unistd.h>
  43. #include <pwd.h>
  44. #include <fcntl.h>
  45. #include <sys/types.h>
  46. #include <sys/stat.h>
  47. #include <signal.h>
  48. #endif
  49. #include "node/Constants.hpp"
  50. #include "node/Defaults.hpp"
  51. #include "node/Utils.hpp"
  52. #include "node/Node.hpp"
  53. #include "node/Condition.hpp"
  54. #include "node/C25519.hpp"
  55. #include "node/Identity.hpp"
  56. using namespace ZeroTier;
  57. static Node *node = (Node *)0;
  58. static void printHelp(const char *cn,FILE *out)
  59. {
  60. fprintf(out,"ZeroTier One version %d.%d.%d"ZT_EOL_S"(c)2012-2013 ZeroTier Networks LLC"ZT_EOL_S,Node::versionMajor(),Node::versionMinor(),Node::versionRevision());
  61. fprintf(out,"Licensed under the GNU General Public License v3"ZT_EOL_S""ZT_EOL_S);
  62. #ifdef ZT_AUTO_UPDATE
  63. fprintf(out,"Auto-update enabled build, will update from URL:"ZT_EOL_S);
  64. fprintf(out," %s"ZT_EOL_S,ZT_DEFAULTS.updateLatestNfoURL.c_str());
  65. fprintf(out,"Update authentication signing authorities: "ZT_EOL_S);
  66. int no = 0;
  67. for(std::map< Address,Identity >::const_iterator sa(ZT_DEFAULTS.updateAuthorities.begin());sa!=ZT_DEFAULTS.updateAuthorities.end();++sa) {
  68. if (no == 0)
  69. fprintf(out," %s",sa->first.toString().c_str());
  70. else fprintf(out,", %s",sa->first.toString().c_str());
  71. if (++no == 6) {
  72. fprintf(out,ZT_EOL_S);
  73. no = 0;
  74. }
  75. }
  76. fprintf(out,ZT_EOL_S""ZT_EOL_S);
  77. #else
  78. fprintf(out,"Auto-updates not enabled on this build. You must update manually."ZT_EOL_S""ZT_EOL_S);
  79. #endif
  80. fprintf(out,"Usage: %s [-switches] [home directory]"ZT_EOL_S""ZT_EOL_S,cn);
  81. fprintf(out,"Available switches:"ZT_EOL_S);
  82. fprintf(out," -h - Display this help"ZT_EOL_S);
  83. fprintf(out," -v - Show version"ZT_EOL_S);
  84. fprintf(out," -p<port> - Bind to this port for network I/O"ZT_EOL_S);
  85. fprintf(out," -c<port> - Bind to this port for local control packets"ZT_EOL_S);
  86. fprintf(out," -q - Send a query to a running service (zerotier-cli)"ZT_EOL_S);
  87. fprintf(out," -i - Run idtool command (zerotier-idtool)"ZT_EOL_S);
  88. }
  89. namespace ZeroTierCLI { // ---------------------------------------------------
  90. static void printHelp(FILE *out,const char *exename)
  91. {
  92. fprintf(out,"Usage: %s [-switches] <command>"ZT_EOL_S,exename);
  93. fprintf(out,ZT_EOL_S);
  94. fprintf(out,"Available switches:"ZT_EOL_S);
  95. fprintf(out," -c<port> - Communicate with daemon over this local port"ZT_EOL_S);
  96. fprintf(out," -t<token> - Specify token on command line"ZT_EOL_S);
  97. fprintf(out," -T<file> - Read token from file"ZT_EOL_S);
  98. fprintf(out,ZT_EOL_S);
  99. fprintf(out,"Use the 'help' command to get help from ZeroTier One itself."ZT_EOL_S);
  100. }
  101. static volatile unsigned int numResults = 0;
  102. static Condition doneCondition;
  103. static void resultHandler(void *arg,unsigned long id,const char *line)
  104. {
  105. ++numResults;
  106. if (strlen(line))
  107. fprintf(stdout,"%s"ZT_EOL_S,line);
  108. else doneCondition.signal();
  109. }
  110. // Runs instead of rest of main() if process is called zerotier-cli or if
  111. // -q is specified as an option.
  112. #ifdef __WINDOWS__
  113. static int main(int argc,_TCHAR* argv[])
  114. #else
  115. static int main(int argc,char **argv)
  116. #endif
  117. {
  118. if (argc <= 1) {
  119. printHelp(stdout,argv[0]);
  120. return -1;
  121. }
  122. std::string authToken;
  123. std::string command;
  124. bool pastSwitches = false;
  125. unsigned int controlPort = 0;
  126. for(int i=1;i<argc;++i) {
  127. if ((argv[i][0] == '-')&&(!pastSwitches)) {
  128. if (strlen(argv[i]) <= 1) {
  129. printHelp(stdout,argv[0]);
  130. return -1;
  131. }
  132. switch(argv[i][1]) {
  133. case 'q': // does nothing, for invocation without binary path name aliasing
  134. if (argv[i][2]) {
  135. printHelp(argv[0],stderr);
  136. return 0;
  137. }
  138. break;
  139. case 'c':
  140. controlPort = Utils::strToUInt(argv[i] + 2);
  141. break;
  142. case 't':
  143. authToken.assign(argv[i] + 2);
  144. break;
  145. case 'T':
  146. if (!Utils::readFile(argv[i] + 2,authToken)) {
  147. fprintf(stdout,"FATAL ERROR: unable to read token from '%s'"ZT_EOL_S,argv[i] + 2);
  148. return -2;
  149. }
  150. break;
  151. case 'h':
  152. printHelp(stdout,argv[0]);
  153. return 0;
  154. default:
  155. return -1;
  156. }
  157. } else {
  158. pastSwitches = true;
  159. if (command.length())
  160. command.push_back(' ');
  161. command.append(argv[i]);
  162. }
  163. }
  164. if (!command.length()) {
  165. printHelp(stdout,argv[0]);
  166. return -1;
  167. }
  168. if (!authToken.length()) {
  169. if (!Utils::readFile(Node::LocalClient::authTokenDefaultUserPath().c_str(),authToken)) {
  170. if (!Utils::readFile(Node::LocalClient::authTokenDefaultSystemPath().c_str(),authToken)) {
  171. fprintf(stdout,"FATAL ERROR: no token specified on command line and could not read '%s' or '%s'"ZT_EOL_S,Node::LocalClient::authTokenDefaultSystemPath().c_str(),Node::LocalClient::authTokenDefaultUserPath().c_str());
  172. return -2;
  173. }
  174. }
  175. }
  176. if (!authToken.length()) {
  177. fprintf(stdout,"FATAL ERROR: could not find auth token"ZT_EOL_S);
  178. return -2;
  179. }
  180. Node::LocalClient client(authToken.c_str(),controlPort,&resultHandler,(void *)0);
  181. client.send(command.c_str());
  182. doneCondition.wait(1000);
  183. if (!numResults) {
  184. fprintf(stdout,"ERROR: no results received. Is ZeroTier One running?"ZT_EOL_S);
  185. return -1;
  186. }
  187. return 0;
  188. }
  189. } // namespace ZeroTierCLI ---------------------------------------------------
  190. namespace ZeroTierIdTool { // ------------------------------------------------
  191. static void printHelp(FILE *out,const char *pn)
  192. {
  193. fprintf(out,"Usage: %s <command> [<args>]"ZT_EOL_S""ZT_EOL_S"Commands:"ZT_EOL_S,pn);
  194. fprintf(out," generate [<identity.secret>] [<identity.public>]"ZT_EOL_S);
  195. fprintf(out," validate <identity.secret/public>"ZT_EOL_S);
  196. fprintf(out," getpublic <identity.secret>"ZT_EOL_S);
  197. fprintf(out," sign <identity.secret> <file>"ZT_EOL_S);
  198. fprintf(out," verify <identity.secret/public> <file> <signature>"ZT_EOL_S);
  199. }
  200. static Identity getIdFromArg(char *arg)
  201. {
  202. Identity id;
  203. if ((strlen(arg) > 32)&&(arg[10] == ':')) { // identity is a literal on the command line
  204. if (id.fromString(arg))
  205. return id;
  206. } else { // identity is to be read from a file
  207. std::string idser;
  208. if (Utils::readFile(arg,idser)) {
  209. if (id.fromString(idser))
  210. return id;
  211. }
  212. }
  213. return Identity();
  214. }
  215. // Runs instead of rest of main() if process is called zerotier-idtool or if
  216. // -i is specified as an option.
  217. #ifdef __WINDOWS__
  218. static int main(int argc,_TCHAR* argv[])
  219. #else
  220. static int main(int argc,char **argv)
  221. #endif
  222. {
  223. if (argc < 2) {
  224. printHelp(stderr,argv[0]);
  225. return -1;
  226. }
  227. if (!strcmp(argv[1],"generate")) {
  228. Identity id;
  229. id.generate();
  230. std::string idser = id.toString(true);
  231. if (argc >= 3) {
  232. if (!Utils::writeFile(argv[2],idser)) {
  233. fprintf(stderr,"Error writing to %s"ZT_EOL_S,argv[2]);
  234. return -1;
  235. } else printf("%s written"ZT_EOL_S,argv[2]);
  236. if (argc >= 4) {
  237. idser = id.toString(false);
  238. if (!Utils::writeFile(argv[3],idser)) {
  239. fprintf(stderr,"Error writing to %s"ZT_EOL_S,argv[3]);
  240. return -1;
  241. } else printf("%s written"ZT_EOL_S,argv[3]);
  242. }
  243. } else printf("%s",idser.c_str());
  244. } else if (!strcmp(argv[1],"validate")) {
  245. if (argc < 3) {
  246. printHelp(stderr,argv[0]);
  247. return -1;
  248. }
  249. Identity id = getIdFromArg(argv[2]);
  250. if (!id) {
  251. fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
  252. return -1;
  253. }
  254. if (!id.locallyValidate()) {
  255. fprintf(stderr,"%s FAILED validation."ZT_EOL_S,argv[2]);
  256. return -1;
  257. } else printf("%s is a valid identity"ZT_EOL_S,argv[2]);
  258. } else if (!strcmp(argv[1],"getpublic")) {
  259. if (argc < 3) {
  260. printHelp(stderr,argv[0]);
  261. return -1;
  262. }
  263. Identity id = getIdFromArg(argv[2]);
  264. if (!id) {
  265. fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
  266. return -1;
  267. }
  268. printf("%s",id.toString(false).c_str());
  269. } else if (!strcmp(argv[1],"sign")) {
  270. if (argc < 4) {
  271. printHelp(stderr,argv[0]);
  272. return -1;
  273. }
  274. Identity id = getIdFromArg(argv[2]);
  275. if (!id) {
  276. fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
  277. return -1;
  278. }
  279. if (!id.hasPrivate()) {
  280. fprintf(stderr,"%s does not contain a private key (must use private to sign)"ZT_EOL_S,argv[2]);
  281. return -1;
  282. }
  283. std::string inf;
  284. if (!Utils::readFile(argv[3],inf)) {
  285. fprintf(stderr,"%s is not readable"ZT_EOL_S,argv[3]);
  286. return -1;
  287. }
  288. C25519::Signature signature = id.sign(inf.data(),(unsigned int)inf.length());
  289. printf("%s",Utils::hex(signature.data,(unsigned int)signature.size()).c_str());
  290. } else if (!strcmp(argv[1],"verify")) {
  291. if (argc < 4) {
  292. printHelp(stderr,argv[0]);
  293. return -1;
  294. }
  295. Identity id = getIdFromArg(argv[2]);
  296. if (!id) {
  297. fprintf(stderr,"Identity argument invalid or file unreadable: %s"ZT_EOL_S,argv[2]);
  298. return -1;
  299. }
  300. std::string inf;
  301. if (!Utils::readFile(argv[3],inf)) {
  302. fprintf(stderr,"%s is not readable"ZT_EOL_S,argv[3]);
  303. return -1;
  304. }
  305. std::string signature(Utils::unhex(argv[4]));
  306. if ((signature.length() > ZT_ADDRESS_LENGTH)&&(id.verify(inf.data(),(unsigned int)inf.length(),signature.data(),(unsigned int)signature.length()))) {
  307. printf("%s signature valid"ZT_EOL_S,argv[3]);
  308. } else {
  309. fprintf(stderr,"%s signature check FAILED"ZT_EOL_S,argv[3]);
  310. return -1;
  311. }
  312. } else {
  313. printHelp(stderr,argv[0]);
  314. return -1;
  315. }
  316. return 0;
  317. }
  318. } // namespace ZeroTierIdTool ------------------------------------------------
  319. #ifdef __UNIX_LIKE__
  320. static void sighandlerQuit(int sig)
  321. {
  322. Node *n = node;
  323. if (n)
  324. n->terminate(Node::NODE_NORMAL_TERMINATION,"terminated by signal");
  325. else exit(0);
  326. }
  327. #endif
  328. #ifdef __WINDOWS__
  329. static BOOL WINAPI _handlerRoutine(DWORD dwCtrlType)
  330. {
  331. switch(dwCtrlType) {
  332. case CTRL_C_EVENT:
  333. case CTRL_BREAK_EVENT:
  334. case CTRL_CLOSE_EVENT:
  335. case CTRL_SHUTDOWN_EVENT:
  336. Node *n = node;
  337. if (n)
  338. n->terminate(Node::NODE_NORMAL_TERMINATION,"terminated by signal");
  339. return TRUE;
  340. }
  341. return FALSE;
  342. }
  343. static BOOL IsCurrentUserLocalAdministrator(void)
  344. {
  345. BOOL fReturn = FALSE;
  346. DWORD dwStatus;
  347. DWORD dwAccessMask;
  348. DWORD dwAccessDesired;
  349. DWORD dwACLSize;
  350. DWORD dwStructureSize = sizeof(PRIVILEGE_SET);
  351. PACL pACL = NULL;
  352. PSID psidAdmin = NULL;
  353. HANDLE hToken = NULL;
  354. HANDLE hImpersonationToken = NULL;
  355. PRIVILEGE_SET ps;
  356. GENERIC_MAPPING GenericMapping;
  357. PSECURITY_DESCRIPTOR psdAdmin = NULL;
  358. SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
  359. /*
  360. Determine if the current thread is running as a user that is a member
  361. of
  362. the local admins group. To do this, create a security descriptor
  363. that
  364. has a DACL which has an ACE that allows only local aministrators
  365. access.
  366. Then, call AccessCheck with the current thread's token and the
  367. security
  368. descriptor. It will say whether the user could access an object if
  369. it
  370. had that security descriptor. Note: you do not need to actually
  371. create
  372. the object. Just checking access against the security descriptor
  373. alone
  374. will be sufficient.
  375. */
  376. const DWORD ACCESS_READ = 1;
  377. const DWORD ACCESS_WRITE = 2;
  378. __try
  379. {
  380. /*
  381. AccessCheck() requires an impersonation token. We first get a
  382. primary
  383. token and then create a duplicate impersonation token. The
  384. impersonation token is not actually assigned to the thread, but is
  385. used in the call to AccessCheck. Thus, this function itself never
  386. impersonates, but does use the identity of the thread. If the
  387. thread
  388. was impersonating already, this function uses that impersonation
  389. context.
  390. */
  391. if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY,
  392. TRUE, &hToken))
  393. {
  394. if (GetLastError() != ERROR_NO_TOKEN)
  395. __leave;
  396. if (!OpenProcessToken(GetCurrentProcess(),
  397. TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))
  398. __leave;
  399. }
  400. if (!DuplicateToken (hToken, SecurityImpersonation,
  401. &hImpersonationToken))
  402. __leave;
  403. /*
  404. Create the binary representation of the well-known SID that
  405. represents the local administrators group. Then create the
  406. security
  407. descriptor and DACL with an ACE that allows only local admins
  408. access.
  409. After that, perform the access check. This will determine whether
  410. the current user is a local admin.
  411. */
  412. if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
  413. SECURITY_BUILTIN_DOMAIN_RID,
  414. DOMAIN_ALIAS_RID_ADMINS,
  415. 0, 0, 0, 0, 0, 0, &psidAdmin))
  416. __leave;
  417. psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  418. if (psdAdmin == NULL)
  419. __leave;
  420. if (!InitializeSecurityDescriptor(psdAdmin,
  421. SECURITY_DESCRIPTOR_REVISION))
  422. __leave;
  423. // Compute size needed for the ACL.
  424. dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +
  425. GetLengthSid(psidAdmin) - sizeof(DWORD);
  426. pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
  427. if (pACL == NULL)
  428. __leave;
  429. if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
  430. __leave;
  431. dwAccessMask= ACCESS_READ | ACCESS_WRITE;
  432. if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask,
  433. psidAdmin))
  434. __leave;
  435. if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))
  436. __leave;
  437. /*
  438. AccessCheck validates a security descriptor somewhat; set the
  439. group
  440. and owner so that enough of the security descriptor is filled out
  441. to
  442. make AccessCheck happy.
  443. */
  444. SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE);
  445. SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);
  446. if (!IsValidSecurityDescriptor(psdAdmin))
  447. __leave;
  448. dwAccessDesired = ACCESS_READ;
  449. /*
  450. Initialize GenericMapping structure even though you
  451. do not use generic rights.
  452. */
  453. GenericMapping.GenericRead = ACCESS_READ;
  454. GenericMapping.GenericWrite = ACCESS_WRITE;
  455. GenericMapping.GenericExecute = 0;
  456. GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;
  457. if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired,
  458. &GenericMapping, &ps, &dwStructureSize, &dwStatus,
  459. &fReturn))
  460. {
  461. fReturn = FALSE;
  462. __leave;
  463. }
  464. }
  465. __finally
  466. {
  467. // Clean up.
  468. if (pACL) LocalFree(pACL);
  469. if (psdAdmin) LocalFree(psdAdmin);
  470. if (psidAdmin) FreeSid(psidAdmin);
  471. if (hImpersonationToken) CloseHandle (hImpersonationToken);
  472. if (hToken) CloseHandle (hToken);
  473. }
  474. return fReturn;
  475. }
  476. #endif // __WINDOWS__
  477. #ifdef __WINDOWS__
  478. int _tmain(int argc, _TCHAR* argv[])
  479. #else
  480. int main(int argc,char **argv)
  481. #endif
  482. {
  483. #ifdef __UNIX_LIKE__
  484. signal(SIGHUP,SIG_IGN);
  485. signal(SIGPIPE,SIG_IGN);
  486. signal(SIGUSR1,SIG_IGN);
  487. signal(SIGUSR2,SIG_IGN);
  488. signal(SIGALRM,SIG_IGN);
  489. signal(SIGINT,&sighandlerQuit);
  490. signal(SIGTERM,&sighandlerQuit);
  491. signal(SIGQUIT,&sighandlerQuit);
  492. #endif
  493. #ifdef __WINDOWS__
  494. WSADATA wsaData;
  495. WSAStartup(MAKEWORD(2,2),&wsaData);
  496. SetConsoleCtrlHandler(&_handlerRoutine,TRUE);
  497. #endif
  498. if ((strstr(argv[0],"zerotier-cli"))||(strstr(argv[0],"ZEROTIER-CLI")))
  499. return ZeroTierCLI::main(argc,argv);
  500. if ((strstr(argv[0],"zerotier-idtool"))||(strstr(argv[0],"ZEROTIER-IDTOOL")))
  501. return ZeroTierIdTool::main(argc,argv);
  502. const char *homeDir = (const char *)0;
  503. unsigned int port = 0;
  504. unsigned int controlPort = 0;
  505. for(int i=1;i<argc;++i) {
  506. if (argv[i][0] == '-') {
  507. switch(argv[i][1]) {
  508. case 'p':
  509. port = Utils::strToUInt(argv[i] + 2);
  510. if (port > 65535) {
  511. printHelp(argv[0],stderr);
  512. return 1;
  513. }
  514. break;
  515. case 'v':
  516. printf("%s"ZT_EOL_S,Node::versionString());
  517. return 0;
  518. case 'c':
  519. controlPort = Utils::strToUInt(argv[i] + 2);
  520. if (controlPort > 65535) {
  521. printHelp(argv[0],stderr);
  522. return 1;
  523. }
  524. break;
  525. case 'q':
  526. if (argv[i][2]) {
  527. printHelp(argv[0],stderr);
  528. return 0;
  529. } else return ZeroTierCLI::main(argc,argv);
  530. case 'i':
  531. if (argv[i][2]) {
  532. printHelp(argv[0],stderr);
  533. return 0;
  534. } else return ZeroTierIdTool::main(argc,argv);
  535. case 'h':
  536. case '?':
  537. default:
  538. printHelp(argv[0],stderr);
  539. return 0;
  540. }
  541. } else {
  542. if (homeDir) {
  543. printHelp(argv[0],stderr);
  544. return 0;
  545. }
  546. homeDir = argv[i];
  547. break;
  548. }
  549. }
  550. if ((!homeDir)||(strlen(homeDir) == 0))
  551. homeDir = ZT_DEFAULTS.defaultHomePath.c_str();
  552. #ifdef __UNIX_LIKE__
  553. if (getuid()) {
  554. fprintf(stderr,"%s: must be run as root (uid==0)\n",argv[0]);
  555. return 1;
  556. }
  557. mkdir(homeDir,0755); // will fail if it already exists
  558. {
  559. char pidpath[4096];
  560. Utils::snprintf(pidpath,sizeof(pidpath),"%s/zerotier-one.pid",homeDir);
  561. FILE *pf = fopen(pidpath,"w");
  562. if (pf) {
  563. fprintf(pf,"%ld",(long)getpid());
  564. fclose(pf);
  565. }
  566. }
  567. #else
  568. #ifdef __WINDOWS__
  569. if (IsCurrentUserLocalAdministrator() != TRUE) {
  570. fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
  571. return 1;
  572. }
  573. #endif
  574. #endif
  575. int exitCode = 0;
  576. try {
  577. node = new Node(homeDir,port,controlPort);
  578. switch(node->run()) {
  579. case Node::NODE_RESTART_FOR_UPGRADE: {
  580. const char *upgPath = node->reasonForTermination();
  581. #ifdef __UNIX_LIKE__
  582. // On Unix-type OSes we exec() right into the upgrade. This in turn will
  583. // end with us being re-launched either via the upgrade itself or something
  584. // like OSX's launchd.
  585. if (upgPath) {
  586. Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
  587. ::execl(upgPath,upgPath,(char *)0);
  588. }
  589. exitCode = 2;
  590. fprintf(stderr,"%s: abnormal termination: unable to execute update at %s\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
  591. #else // not __UNIX_LIKE
  592. #ifdef __WINDOWS__
  593. // On Windows the service checks updates.d and invokes updates if they are
  594. // found there. This only happens after exit code 4. The Windows service
  595. // will listen to stdout as well to catch the filename.
  596. if (upgPath) {
  597. printf("[[[ UPDATE AVAILABLE: \"%s\" ]]]\r\n",upgPath);
  598. exitCode = 4;
  599. } else {
  600. exitCode = 2;
  601. }
  602. #endif // __WINDOWS__
  603. #endif // not __UNIX_LIKE__
  604. } break;
  605. case Node::NODE_UNRECOVERABLE_ERROR: {
  606. exitCode = 3;
  607. const char *termReason = node->reasonForTermination();
  608. fprintf(stderr,"%s: abnormal termination: %s\n",argv[0],(termReason) ? termReason : "(unknown reason)");
  609. } break;
  610. default:
  611. break;
  612. }
  613. delete node;
  614. node = (Node *)0;
  615. } catch ( ... ) {}
  616. #ifdef __UNIX_LIKE__
  617. Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
  618. #endif
  619. return exitCode;
  620. }