main.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  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 sighandlerHup(int sig)
  321. {
  322. Node *n = node;
  323. if (n)
  324. n->resync();
  325. }
  326. static void sighandlerQuit(int sig)
  327. {
  328. Node *n = node;
  329. if (n)
  330. n->terminate(Node::NODE_NORMAL_TERMINATION,"terminated by signal");
  331. else exit(0);
  332. }
  333. #endif
  334. #ifdef __WINDOWS__
  335. static BOOL WINAPI _handlerRoutine(DWORD dwCtrlType)
  336. {
  337. switch(dwCtrlType) {
  338. case CTRL_C_EVENT:
  339. case CTRL_BREAK_EVENT:
  340. case CTRL_CLOSE_EVENT:
  341. case CTRL_SHUTDOWN_EVENT:
  342. Node *n = node;
  343. if (n)
  344. n->terminate(Node::NODE_NORMAL_TERMINATION,"terminated by signal");
  345. return TRUE;
  346. }
  347. return FALSE;
  348. }
  349. static BOOL IsCurrentUserLocalAdministrator(void)
  350. {
  351. BOOL fReturn = FALSE;
  352. DWORD dwStatus;
  353. DWORD dwAccessMask;
  354. DWORD dwAccessDesired;
  355. DWORD dwACLSize;
  356. DWORD dwStructureSize = sizeof(PRIVILEGE_SET);
  357. PACL pACL = NULL;
  358. PSID psidAdmin = NULL;
  359. HANDLE hToken = NULL;
  360. HANDLE hImpersonationToken = NULL;
  361. PRIVILEGE_SET ps;
  362. GENERIC_MAPPING GenericMapping;
  363. PSECURITY_DESCRIPTOR psdAdmin = NULL;
  364. SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
  365. /*
  366. Determine if the current thread is running as a user that is a member
  367. of
  368. the local admins group. To do this, create a security descriptor
  369. that
  370. has a DACL which has an ACE that allows only local aministrators
  371. access.
  372. Then, call AccessCheck with the current thread's token and the
  373. security
  374. descriptor. It will say whether the user could access an object if
  375. it
  376. had that security descriptor. Note: you do not need to actually
  377. create
  378. the object. Just checking access against the security descriptor
  379. alone
  380. will be sufficient.
  381. */
  382. const DWORD ACCESS_READ = 1;
  383. const DWORD ACCESS_WRITE = 2;
  384. __try
  385. {
  386. /*
  387. AccessCheck() requires an impersonation token. We first get a
  388. primary
  389. token and then create a duplicate impersonation token. The
  390. impersonation token is not actually assigned to the thread, but is
  391. used in the call to AccessCheck. Thus, this function itself never
  392. impersonates, but does use the identity of the thread. If the
  393. thread
  394. was impersonating already, this function uses that impersonation
  395. context.
  396. */
  397. if (!OpenThreadToken(GetCurrentThread(), TOKEN_DUPLICATE|TOKEN_QUERY,
  398. TRUE, &hToken))
  399. {
  400. if (GetLastError() != ERROR_NO_TOKEN)
  401. __leave;
  402. if (!OpenProcessToken(GetCurrentProcess(),
  403. TOKEN_DUPLICATE|TOKEN_QUERY, &hToken))
  404. __leave;
  405. }
  406. if (!DuplicateToken (hToken, SecurityImpersonation,
  407. &hImpersonationToken))
  408. __leave;
  409. /*
  410. Create the binary representation of the well-known SID that
  411. represents the local administrators group. Then create the
  412. security
  413. descriptor and DACL with an ACE that allows only local admins
  414. access.
  415. After that, perform the access check. This will determine whether
  416. the current user is a local admin.
  417. */
  418. if (!AllocateAndInitializeSid(&SystemSidAuthority, 2,
  419. SECURITY_BUILTIN_DOMAIN_RID,
  420. DOMAIN_ALIAS_RID_ADMINS,
  421. 0, 0, 0, 0, 0, 0, &psidAdmin))
  422. __leave;
  423. psdAdmin = LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
  424. if (psdAdmin == NULL)
  425. __leave;
  426. if (!InitializeSecurityDescriptor(psdAdmin,
  427. SECURITY_DESCRIPTOR_REVISION))
  428. __leave;
  429. // Compute size needed for the ACL.
  430. dwACLSize = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) +
  431. GetLengthSid(psidAdmin) - sizeof(DWORD);
  432. pACL = (PACL)LocalAlloc(LPTR, dwACLSize);
  433. if (pACL == NULL)
  434. __leave;
  435. if (!InitializeAcl(pACL, dwACLSize, ACL_REVISION2))
  436. __leave;
  437. dwAccessMask= ACCESS_READ | ACCESS_WRITE;
  438. if (!AddAccessAllowedAce(pACL, ACL_REVISION2, dwAccessMask,
  439. psidAdmin))
  440. __leave;
  441. if (!SetSecurityDescriptorDacl(psdAdmin, TRUE, pACL, FALSE))
  442. __leave;
  443. /*
  444. AccessCheck validates a security descriptor somewhat; set the
  445. group
  446. and owner so that enough of the security descriptor is filled out
  447. to
  448. make AccessCheck happy.
  449. */
  450. SetSecurityDescriptorGroup(psdAdmin, psidAdmin, FALSE);
  451. SetSecurityDescriptorOwner(psdAdmin, psidAdmin, FALSE);
  452. if (!IsValidSecurityDescriptor(psdAdmin))
  453. __leave;
  454. dwAccessDesired = ACCESS_READ;
  455. /*
  456. Initialize GenericMapping structure even though you
  457. do not use generic rights.
  458. */
  459. GenericMapping.GenericRead = ACCESS_READ;
  460. GenericMapping.GenericWrite = ACCESS_WRITE;
  461. GenericMapping.GenericExecute = 0;
  462. GenericMapping.GenericAll = ACCESS_READ | ACCESS_WRITE;
  463. if (!AccessCheck(psdAdmin, hImpersonationToken, dwAccessDesired,
  464. &GenericMapping, &ps, &dwStructureSize, &dwStatus,
  465. &fReturn))
  466. {
  467. fReturn = FALSE;
  468. __leave;
  469. }
  470. }
  471. __finally
  472. {
  473. // Clean up.
  474. if (pACL) LocalFree(pACL);
  475. if (psdAdmin) LocalFree(psdAdmin);
  476. if (psidAdmin) FreeSid(psidAdmin);
  477. if (hImpersonationToken) CloseHandle (hImpersonationToken);
  478. if (hToken) CloseHandle (hToken);
  479. }
  480. return fReturn;
  481. }
  482. #endif // __WINDOWS__
  483. #ifdef __WINDOWS__
  484. int _tmain(int argc, _TCHAR* argv[])
  485. #else
  486. int main(int argc,char **argv)
  487. #endif
  488. {
  489. #ifdef __UNIX_LIKE__
  490. signal(SIGHUP,&sighandlerHup);
  491. signal(SIGPIPE,SIG_IGN);
  492. signal(SIGUSR1,SIG_IGN);
  493. signal(SIGUSR2,SIG_IGN);
  494. signal(SIGALRM,SIG_IGN);
  495. signal(SIGINT,&sighandlerQuit);
  496. signal(SIGTERM,&sighandlerQuit);
  497. signal(SIGQUIT,&sighandlerQuit);
  498. #endif
  499. #ifdef __WINDOWS__
  500. WSADATA wsaData;
  501. WSAStartup(MAKEWORD(2,2),&wsaData);
  502. SetConsoleCtrlHandler(&_handlerRoutine,TRUE);
  503. #endif
  504. if ((strstr(argv[0],"zerotier-cli"))||(strstr(argv[0],"ZEROTIER-CLI")))
  505. return ZeroTierCLI::main(argc,argv);
  506. if ((strstr(argv[0],"zerotier-idtool"))||(strstr(argv[0],"ZEROTIER-IDTOOL")))
  507. return ZeroTierIdTool::main(argc,argv);
  508. const char *homeDir = (const char *)0;
  509. unsigned int port = 0;
  510. unsigned int controlPort = 0;
  511. for(int i=1;i<argc;++i) {
  512. if (argv[i][0] == '-') {
  513. switch(argv[i][1]) {
  514. case 'p':
  515. port = Utils::strToUInt(argv[i] + 2);
  516. if (port > 65535) {
  517. printHelp(argv[0],stderr);
  518. return 1;
  519. }
  520. break;
  521. case 'v':
  522. printf("%s"ZT_EOL_S,Node::versionString());
  523. return 0;
  524. case 'c':
  525. controlPort = Utils::strToUInt(argv[i] + 2);
  526. if (controlPort > 65535) {
  527. printHelp(argv[0],stderr);
  528. return 1;
  529. }
  530. break;
  531. case 'q':
  532. if (argv[i][2]) {
  533. printHelp(argv[0],stderr);
  534. return 0;
  535. } else return ZeroTierCLI::main(argc,argv);
  536. case 'i':
  537. if (argv[i][2]) {
  538. printHelp(argv[0],stderr);
  539. return 0;
  540. } else return ZeroTierIdTool::main(argc,argv);
  541. case 'h':
  542. case '?':
  543. default:
  544. printHelp(argv[0],stderr);
  545. return 0;
  546. }
  547. } else {
  548. if (homeDir) {
  549. printHelp(argv[0],stderr);
  550. return 0;
  551. }
  552. homeDir = argv[i];
  553. break;
  554. }
  555. }
  556. if ((!homeDir)||(strlen(homeDir) == 0))
  557. homeDir = ZT_DEFAULTS.defaultHomePath.c_str();
  558. #ifdef __UNIX_LIKE__
  559. if (getuid()) {
  560. fprintf(stderr,"%s: must be run as root (uid==0)\n",argv[0]);
  561. return 1;
  562. }
  563. mkdir(homeDir,0755); // will fail if it already exists
  564. {
  565. char pidpath[4096];
  566. Utils::snprintf(pidpath,sizeof(pidpath),"%s/zerotier-one.pid",homeDir);
  567. FILE *pf = fopen(pidpath,"w");
  568. if (pf) {
  569. fprintf(pf,"%ld",(long)getpid());
  570. fclose(pf);
  571. }
  572. }
  573. #else
  574. #ifdef __WINDOWS__
  575. if (IsCurrentUserLocalAdministrator() != TRUE) {
  576. fprintf(stderr,"%s: must be run as a local administrator."ZT_EOL_S,argv[0]);
  577. return 1;
  578. }
  579. #endif
  580. #endif
  581. int exitCode = 0;
  582. try {
  583. node = new Node(homeDir,port,controlPort);
  584. switch(node->run()) {
  585. case Node::NODE_RESTART_FOR_UPGRADE: {
  586. const char *upgPath = node->reasonForTermination();
  587. #ifdef __UNIX_LIKE__
  588. // On Unix-type OSes we exec() right into the upgrade. This in turn will
  589. // end with us being re-launched either via the upgrade itself or something
  590. // like OSX's launchd.
  591. if (upgPath) {
  592. Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
  593. ::execl(upgPath,upgPath,(char *)0);
  594. }
  595. exitCode = 2;
  596. fprintf(stderr,"%s: abnormal termination: unable to execute update at %s\n",argv[0],(upgPath) ? upgPath : "(unknown path)");
  597. #else // not __UNIX_LIKE
  598. #ifdef __WINDOWS__
  599. // On Windows the service checks updates.d and invokes updates if they are
  600. // found there. This only happens after exit code 4. The Windows service
  601. // will listen to stdout as well to catch the filename.
  602. if (upgPath) {
  603. printf("[[[ UPDATE AVAILABLE: \"%s\" ]]]\r\n",upgPath);
  604. exitCode = 4;
  605. } else {
  606. exitCode = 2;
  607. }
  608. #endif // __WINDOWS__
  609. #endif // not __UNIX_LIKE__
  610. } break;
  611. case Node::NODE_UNRECOVERABLE_ERROR: {
  612. exitCode = 3;
  613. const char *termReason = node->reasonForTermination();
  614. fprintf(stderr,"%s: abnormal termination: %s\n",argv[0],(termReason) ? termReason : "(unknown reason)");
  615. } break;
  616. default:
  617. break;
  618. }
  619. delete node;
  620. node = (Node *)0;
  621. } catch ( ... ) {}
  622. #ifdef __UNIX_LIKE__
  623. Utils::rm((std::string(homeDir)+"/zerotier-one.pid").c_str());
  624. #endif
  625. return exitCode;
  626. }