installer.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  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. /*
  28. * This can be run to install ZT1 for the first time or to update it. It
  29. * carries all payloads internally as LZ4 compressed blobs.
  30. */
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <stdint.h>
  35. #include "node/Constants.hpp"
  36. #include "version.h"
  37. #ifdef __WINDOWS__
  38. #include <Windows.h>
  39. #include <tchar.h>
  40. #include <wchar.h>
  41. #else
  42. #include <unistd.h>
  43. #include <pwd.h>
  44. #include <dirent.h>
  45. #include <fcntl.h>
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #include <sys/wait.h>
  49. #include <signal.h>
  50. #endif
  51. #include "ext/lz4/lz4.h"
  52. #include "ext/lz4/lz4hc.h"
  53. /* Include LZ4 comrpessed blobs ********************************************/
  54. /* zerotier-one binary (or zerotier-one.exe for Windows) */
  55. #include "installer-build/zerotier_one.h"
  56. /* Unix uninstall script, installed in home for user to remove */
  57. #ifdef __UNIX_LIKE__
  58. #include "installer-build/uninstall_sh.h"
  59. #endif
  60. /* Linux init.d script */
  61. #ifdef __LINUX__
  62. #include "installer-build/linux__init_d__zerotier_one.h"
  63. #endif
  64. /* Apple Tap device driver, launchd plist, and /Applications app */
  65. #ifdef __APPLE__
  66. #include "installer-build/tap_mac__Info_plist.h"
  67. #include "installer-build/tap_mac__tap.h"
  68. #include "installer-build/mac__launch_sh.h"
  69. #include "installer-build/mac__com_zerotier_one_plist.h"
  70. #include "installer-build/mac_ui__contents_info_plist.h"
  71. #include "installer-build/mac_ui__contents_macos_zerotier_one.h"
  72. #include "installer-build/mac_ui__contents_pkginfo.h"
  73. #include "installer-build/mac_ui__contents_resources_empty_lproj.h"
  74. #include "installer-build/mac_ui__contents_resources_zt1icon_icns.h"
  75. #endif
  76. /* Windows Tap device drivers for x86 and x64 (installer will be x86) */
  77. #ifdef __WINDOWS__
  78. #include "installer-build/tap_windows__x64__ztTap100_sys.h"
  79. #include "installer-build/tap_windows__x64__ztTap100_inf.h"
  80. #include "installer-build/tap_windows__x86__ztTap100_sys.h"
  81. #include "installer-build/tap_windows__x86__ztTap100_inf.h"
  82. #include "installer-build/tap_windows__devcon32_exe.h"
  83. #include "installer-build/tap_windows__devcon64_exe.h"
  84. #endif
  85. /***************************************************************************/
  86. static unsigned char *_unlz4(const void *lz4,int decompressedLen)
  87. {
  88. unsigned char *buf;
  89. if (!decompressedLen)
  90. return (unsigned char *)0;
  91. buf = (unsigned char *)malloc(decompressedLen);
  92. if (!buf)
  93. return (unsigned char *)0;
  94. if (LZ4_decompress_fast((const char *)lz4,(char *)buf,decompressedLen) <= 0) {
  95. free(buf);
  96. return (unsigned char *)0;
  97. }
  98. return buf;
  99. }
  100. static int _putBlob(const void *lz4,int decompressedLen,const char *path,int executable,int protect,int preserveOwnership)
  101. {
  102. unsigned char *data = _unlz4(lz4,decompressedLen);
  103. if ((!data)&&(decompressedLen))
  104. return 0;
  105. #ifdef __WINDOWS__
  106. DeleteFileA(path);
  107. #else
  108. struct stat oldModes;
  109. int hasOldModes = ((stat(path,&oldModes) == 0) ? 1 : 0);
  110. unlink(path);
  111. #endif
  112. FILE *f = fopen(path,"wb");
  113. if (!f) {
  114. free(data);
  115. return 0;
  116. }
  117. if ((decompressedLen)&&(fwrite(data,decompressedLen,1,f) != 1)) {
  118. fclose(f);
  119. free(data);
  120. #ifdef __WINDOWS__
  121. DeleteFileA(path);
  122. #else
  123. unlink(path);
  124. #endif
  125. return 0;
  126. }
  127. fclose(f);
  128. #ifdef __WINDOWS__
  129. /* TODO: Windows exec/prot/etc. */
  130. #else
  131. if (executable) {
  132. if (protect)
  133. chmod(path,0700);
  134. else chmod(path,0755);
  135. } else {
  136. if (protect)
  137. chmod(path,0600);
  138. else chmod(path,0644);
  139. }
  140. if (preserveOwnership&&hasOldModes)
  141. chown(path,oldModes.st_uid,oldModes.st_gid);
  142. else chown(path,0,0);
  143. #endif
  144. free(data);
  145. return 1;
  146. }
  147. #define putBlob(name,path,exec,prot,pres) _putBlob((name),(name##_UNCOMPRESSED_LEN),(path),(exec),(prot),(pres))
  148. #ifdef __WINDOWS__
  149. int _tmain(int argc, _TCHAR* argv[])
  150. #else
  151. int main(int argc,char **argv)
  152. #endif
  153. {
  154. /* Installer/updater for Unix-like systems (including Mac) */
  155. #ifdef __UNIX_LIKE__ /******************************************************/
  156. char buf[4096];
  157. if (getuid() != 0) {
  158. printf("! ZeroTier One installer must be run as root.\n");
  159. return 2;
  160. }
  161. printf("# ZeroTier One installer/updater starting...\n");
  162. /* Create home folder */
  163. const char *zthome;
  164. #ifdef __APPLE__
  165. mkdir("/Library/Application Support/ZeroTier",0755);
  166. chmod("/Library/Application Support/ZeroTier",0755);
  167. chown("/Library/Application Support/ZeroTier",0,0);
  168. printf("mkdir /Library/Application Support/ZeroTier\n");
  169. mkdir(zthome = "/Library/Application Support/ZeroTier/One",0755);
  170. #else /* not Apple */
  171. mkdir("/var/lib",0755);
  172. printf("mkdir /var/lib\n");
  173. mkdir(zthome = "/var/lib/zerotier-one",0755);
  174. #endif
  175. chmod(zthome,0755);
  176. chown(zthome,0,0);
  177. printf("mkdir %s\n",zthome);
  178. /* Write main ZT1 binary */
  179. sprintf(buf,"%s/zerotier-one",zthome);
  180. if (!putBlob(zerotier_one,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  181. /* Create command line interface symlink */
  182. unlink("/usr/bin/zerotier-cli");
  183. symlink(buf,"/usr/bin/zerotier-cli");
  184. printf("link %s /usr/bin/zerotier-cli\n",buf);
  185. /* Write uninstall script into home folder */
  186. sprintf(buf,"%s/uninstall.sh",zthome);
  187. if (!putBlob(uninstall_sh,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  188. #ifdef __APPLE__
  189. /* Write launcher script for Mac */
  190. sprintf(buf,"%s/launch.sh",zthome);
  191. if (!putBlob(mac__launch_sh,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  192. /* Add ZT1 task to Apple's launchd */
  193. sprintf(buf,"/Library/LaunchDaemons/com.zerotier.one.plist");
  194. if (!putBlob(mac__com_zerotier_one_plist,buf,0,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  195. /* Write tap.kext into home folder */
  196. sprintf(buf,"%s/tap.kext",zthome);
  197. mkdir(buf,0755); chmod(buf,0755); chown(buf,0,0); printf("mkdir %s\n",buf);
  198. sprintf(buf,"%s/tap.kext/Contents",zthome);
  199. mkdir(buf,0755); chmod(buf,0755); chown(buf,0,0); printf("mkdir %s\n",buf);
  200. sprintf(buf,"%s/tap.kext/Contents/MacOS",zthome);
  201. mkdir(buf,0755); chmod(buf,0755); chown(buf,0,0); printf("mkdir %s\n",buf);
  202. sprintf(buf,"%s/tap.kext/Contents/Info.plist",zthome);
  203. if (!putBlob(tap_mac__Info_plist,buf,0,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  204. sprintf(buf,"%s/tap.kext/Contents/MacOS/tap",zthome);
  205. if (!putBlob(tap_mac__tap,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  206. /* Write or update GUI application into /Applications */
  207. sprintf(buf,"/Applications/ZeroTier One.app");
  208. mkdir(buf,0755); chmod(buf,0755); chown(buf,0,0); printf("mkdir %s\n",buf);
  209. sprintf(buf,"/Applications/ZeroTier One.app/Contents");
  210. mkdir(buf,0755); chmod(buf,0755); chown(buf,0,0); printf("mkdir %s\n",buf);
  211. sprintf(buf,"/Applications/ZeroTier One.app/Contents/MacOS");
  212. mkdir(buf,0755); chmod(buf,0755); chown(buf,0,0); printf("mkdir %s\n",buf);
  213. sprintf(buf,"/Applications/ZeroTier One.app/Contents/Resources");
  214. mkdir(buf,0755); chmod(buf,0755); chown(buf,0,0); printf("mkdir %s\n",buf);
  215. sprintf(buf,"/Applications/ZeroTier One.app/Contents/Info.plist");
  216. if (!putBlob(mac_ui__contents_info_plist,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  217. sprintf(buf,"/Applications/ZeroTier One.app/Contents/MacOS/ZeroTier One");
  218. if (!putBlob(mac_ui__contents_macos_zerotier_one,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  219. sprintf(buf,"/Applications/ZeroTier One.app/Contents/PkgInfo");
  220. if (!putBlob(mac_ui__contents_pkginfo,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  221. sprintf(buf,"/Applications/ZeroTier One.app/Contents/Resources/empty.lproj");
  222. if (!putBlob(mac_ui__contents_resources_empty_lproj,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  223. sprintf(buf,"/Applications/ZeroTier One.app/Contents/Resources/zt1icon.icns");
  224. if (!putBlob(mac_ui__contents_resources_zt1icon_icns,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  225. /* Load script into running launchd, start ZeroTier One */
  226. printf("exec launchctl load /Library/LaunchDaemons/com.zerotier.one.plist: "); fflush(stdout);
  227. long launchctlpid = (long)vfork();
  228. if (launchctlpid == 0) {
  229. execl("/bin/launchctl","/bin/launchctl","load","/Library/LaunchDaemons/com.zerotier.one.plist",(char *)0);
  230. execlp("launchctl","launchctl","load","/Library/LaunchDaemons/com.zerotier.one.plist",(char *)0); /* reached if execl() with full path fails */
  231. exit(0); /* never reached on successful execl() or execlp() */
  232. }
  233. if (launchctlpid > 0) {
  234. int exitcode = 0;
  235. waitpid(launchctlpid,&exitcode,0);
  236. }
  237. printf("installed.\n");
  238. #endif /* __APPLE__ */
  239. #ifdef __LINUX__
  240. /* Write Linux init script */
  241. sprintf(buf,"/etc/init.d/zerotier-one");
  242. if (!putBlob(linux__init_d__zerotier_one,buf,1,0,0)) { printf("! unable to write %s\n",buf); return 1; } printf("write %s\n",buf);
  243. /* Erase any previous startup/shutdown links */
  244. for(int rl=0;rl<=6;++rl) {
  245. sprintf(buf,"/etc/rc%d.d",rl);
  246. DIR *rcd = opendir(buf);
  247. if (rcd) {
  248. struct dirent *d;
  249. while ((d = readdir(rcd))) {
  250. if (strstr(d->d_name,"zerotier-one")) {
  251. sprintf(buf,"/etc/rc%d.d/%s",rl,d->d_name);
  252. unlink(buf);
  253. printf("rm %s\n",buf);
  254. }
  255. }
  256. closedir(rcd);
  257. }
  258. }
  259. /* Link init script to all the proper places for startup/shutdown */
  260. symlink("/etc/init.d/zerotier-one","/etc/rc0.d/K89zerotier-one");
  261. printf("link /etc/init.d/zerotier-one /etc/rc0.d/K89zerotier-one\n");
  262. symlink("/etc/init.d/zerotier-one","/etc/rc1.d/K89zerotier-one");
  263. printf("link /etc/init.d/zerotier-one /etc/rc1.d/K89zerotier-one\n");
  264. symlink("/etc/init.d/zerotier-one","/etc/rc2.d/S11zerotier-one");
  265. printf("link /etc/init.d/zerotier-one /etc/rc2.d/S11zerotier-one\n");
  266. symlink("/etc/init.d/zerotier-one","/etc/rc3.d/S11zerotier-one");
  267. printf("link /etc/init.d/zerotier-one /etc/rc3.d/S11zerotier-one\n");
  268. symlink("/etc/init.d/zerotier-one","/etc/rc4.d/S11zerotier-one");
  269. printf("link /etc/init.d/zerotier-one /etc/rc4.d/S11zerotier-one\n");
  270. symlink("/etc/init.d/zerotier-one","/etc/rc5.d/S11zerotier-one");
  271. printf("link /etc/init.d/zerotier-one /etc/rc5.d/S11zerotier-one\n");
  272. symlink("/etc/init.d/zerotier-one","/etc/rc6.d/K89zerotier-one");
  273. printf("link /etc/init.d/zerotier-one /etc/rc6.d/K89zerotier-one\n");
  274. #endif /* __LINUX__ */
  275. printf("# Done!\n");
  276. /* -s causes this to exec() itself to ZeroTier One after install/update */
  277. if ((argc > 1)&&(!strcmp(argv[1],"-s"))) {
  278. sprintf(buf,"%s/zerotier-one",zthome);
  279. printf("# -s specified, proceeding to exec(%s)\n",zthome);
  280. execl(buf,buf,(char *)0);
  281. return 3; /* never reached on successful execl() */
  282. }
  283. #endif /* __UNIX_LIKE__ ****************************************************/
  284. /* Installer/updater for Windows systems */
  285. #ifdef __WINDOWS__ /********************************************************/
  286. #endif /* __WINDOWS__ ******************************************************/
  287. return 0;
  288. }