vlmcsd.c 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819
  1. #ifndef _CRT_SECURE_NO_WARNINGS
  2. #define _CRT_SECURE_NO_WARNINGS
  3. #endif
  4. #ifndef CONFIG
  5. #define CONFIG "config.h"
  6. #endif // CONFIG
  7. #include CONFIG
  8. #if defined(USE_MSRPC) && !defined(_WIN32) && !defined(__CYGWIN__)
  9. #error Microsoft RPC is only available on Windows and Cygwin
  10. #endif
  11. #if defined(USE_MSRPC) && defined(SIMPLE_SOCKETS)
  12. #error You can only define either USE_MSRPC or SIMPLE_SOCKETS but not both
  13. #endif
  14. #if defined(NO_SOCKETS) && defined(USE_MSRPC)
  15. #error Cannot use inetd mode with Microsoft RPC
  16. #endif
  17. #ifndef _GNU_SOURCE
  18. #define _GNU_SOURCE
  19. #endif
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <stdint.h>
  25. #if _MSC_VER
  26. #include "wingetopt.h"
  27. #endif
  28. #ifndef _WIN32
  29. #include <pwd.h>
  30. #include <grp.h>
  31. #include <sys/types.h>
  32. #if !defined(NO_LIMIT) && !__minix__
  33. #include <sys/ipc.h>
  34. #if !__ANDROID__
  35. #include <sys/shm.h>
  36. #else // __ANDROID__
  37. #include <sys/syscall.h>
  38. #endif // __ANDROID__
  39. #endif // !defined(NO_LIMIT) && !__minix__
  40. #include <sys/wait.h>
  41. #include <unistd.h>
  42. #include <fcntl.h>
  43. #include <sys/stat.h>
  44. #ifndef NO_LIMIT
  45. #include <semaphore.h>
  46. #endif // NO_LIMIT
  47. #endif // !_WIN32
  48. #if __APPLE__
  49. #include <mach-o/dyld.h>
  50. #endif // __APPLE__
  51. #if __linux__ && defined(USE_AUXV)
  52. #include <sys/auxv.h>
  53. #endif
  54. #if __FreeBSD__
  55. #include <sys/sysctl.h>
  56. #endif
  57. #include "vlmcsd.h"
  58. #include "endian.h"
  59. #include "shared_globals.h"
  60. #include "output.h"
  61. #ifndef USE_MSRPC
  62. #include "network.h"
  63. #else // USE_MSRPC
  64. #include "msrpc-server.h"
  65. #endif // USE_MSRPC
  66. #include "ntservice.h"
  67. #include "helpers.h"
  68. static const char* const optstring = "N:B:m:t:w:0:3:6:H:A:R:u:g:L:p:i:P:l:r:U:W:C:F:o:T:SseDdVvqkZ";
  69. #if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
  70. static uint_fast8_t maxsockets = 0;
  71. #endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
  72. #ifdef _NTSERVICE
  73. static int_fast8_t installService = 0;
  74. static const char *restrict ServiceUser = NULL;
  75. static const char *restrict ServicePassword = "";
  76. #endif
  77. #ifndef NO_PID_FILE
  78. static const char *fn_pid = NULL;
  79. #endif
  80. #ifndef NO_INI_FILE
  81. #ifdef INI_FILE
  82. static const char *fn_ini = INI_FILE;
  83. #else // !INI_FILE
  84. static const char *fn_ini = NULL;
  85. #endif // !INI_FILE
  86. static const char* IniFileErrorMessage = "";
  87. char* IniFileErrorBuffer = NULL;
  88. #define INIFILE_ERROR_BUFFERSIZE 256
  89. static IniFileParameter_t IniFileParameterList[] =
  90. {
  91. { "Windows", INI_PARAM_WINDOWS },
  92. { "Office2010", INI_PARAM_OFFICE2010 },
  93. { "Office2013", INI_PARAM_OFFICE2013 },
  94. { "Office2016", INI_PARAM_OFFICE2016 },
  95. # ifndef NO_RANDOM_EPID
  96. { "RandomizationLevel", INI_PARAM_RANDOMIZATION_LEVEL },
  97. { "LCID", INI_PARAM_LCID },
  98. # endif // NO_RANDOM_EPID
  99. # if !defined(NO_SOCKETS) && (defined(USE_MSRPC) || defined(SIMPLE_SOCKETS) || defined(HAVE_GETIFADDR))
  100. { "Port", INI_PARAM_PORT },
  101. # endif // defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)
  102. # if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
  103. # ifndef SIMPLE_SOCKETS
  104. { "Listen", INI_PARAM_LISTEN },
  105. # endif // SIMPLE_SOCKETS
  106. # if HAVE_FREEBIND
  107. { "FreeBind", INI_PARAM_FREEBIND },
  108. # endif // HAVE_FREEBIND
  109. # if !defined(NO_LIMIT) && !__minix__
  110. { "MaxWorkers", INI_PARAM_MAX_WORKERS },
  111. # endif // !defined(NO_LIMIT) && !__minix__
  112. # endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
  113. # if !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC) & !defined(USE_MSRPC)
  114. { "ConnectionTimeout", INI_PARAM_CONNECTION_TIMEOUT },
  115. # endif // !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC) & !defined(USE_MSRPC)
  116. # ifndef USE_MSRPC
  117. { "DisconnectClientsImmediately", INI_PARAM_DISCONNECT_IMMEDIATELY },
  118. { "UseNDR64", INI_PARAM_RPC_NDR64 },
  119. { "UseBTFN", INI_PARAM_RPC_BTFN },
  120. # endif // USE_MSRPC
  121. # ifndef NO_PID_FILE
  122. { "PIDFile", INI_PARAM_PID_FILE },
  123. # endif // NO_PID_FILE
  124. # ifndef NO_LOG
  125. { "LogDateAndTime", INI_PARAM_LOG_DATE_AND_TIME },
  126. { "LogFile", INI_PARAM_LOG_FILE },
  127. # ifndef NO_VERBOSE_LOG
  128. { "LogVerbose", INI_PARAM_LOG_VERBOSE },
  129. # endif // NO_VERBOSE_LOG
  130. # endif // NO_LOG
  131. # ifndef NO_CUSTOM_INTERVALS
  132. {"ActivationInterval", INI_PARAM_ACTIVATION_INTERVAL },
  133. {"RenewalInterval", INI_PARAM_RENEWAL_INTERVAL },
  134. # endif // NO_CUSTOM_INTERVALS
  135. # if !defined(NO_USER_SWITCH) && !defined(_WIN32)
  136. { "user", INI_PARAM_UID },
  137. { "group", INI_PARAM_GID},
  138. # endif // !defined(NO_USER_SWITCH) && !defined(_WIN32)
  139. # if !defined(NO_PRIVATE_IP_DETECT)
  140. {"PublicIPProtectionLevel", INI_PARAM_PUBLIC_IP_PROTECTION_LEVEL },
  141. # endif
  142. };
  143. #endif // NO_INI_FILE
  144. #if !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
  145. #if !defined(USE_THREADS) && !defined(CYGWIN) && !defined(USE_MSRPC)
  146. static int shmid = -1;
  147. #endif
  148. #if __ANDROID__ && !defined(USE_THREADS) // Bionic does not wrap these syscalls (willingly because Google fears, developers don't know how to use it)
  149. #ifdef __NR_shmget
  150. static int shmget(key_t key, size_t size, int shmflg)
  151. {
  152. return syscall(__NR_shmget, key, size, shmflg);
  153. }
  154. #endif // __NR_shmget
  155. #ifdef __NR_shmat
  156. static void *shmat(int shmid, const void *shmaddr, int shmflg)
  157. {
  158. return (void *)syscall(__NR_shmat, shmid, shmaddr, shmflg);
  159. }
  160. #endif // __NR_shmat
  161. #ifdef __NR_shmdt
  162. static int shmdt(const void *shmaddr)
  163. {
  164. return syscall(__NR_shmdt, shmaddr);
  165. }
  166. #endif // __NR_shmdt
  167. #ifdef __NR_shmctl
  168. static int shmctl(int shmid, int cmd, /*struct shmid_ds*/void *buf)
  169. {
  170. return syscall(__NR_shmctl, shmid, cmd, buf);
  171. }
  172. #endif // __NR_shmctl
  173. #endif // __ANDROID__ && !defined(USE_THREADS)
  174. #endif // !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
  175. #ifndef NO_USER_SWITCH
  176. #ifndef _WIN32
  177. static const char *uname = NULL, *gname = NULL;
  178. static gid_t gid = INVALID_GID;
  179. static uid_t uid = INVALID_UID;
  180. // Get Numeric id of user/group
  181. static char GetNumericId(gid_t *restrict id, const char *const c)
  182. {
  183. char* endptr;
  184. gid_t temp;
  185. temp = (gid_t)strtoll(c, &endptr, 10);
  186. if (!*endptr) *id = temp;
  187. if (*endptr || temp == (gid_t)-1) errno = EINVAL;
  188. return *endptr || *id == (gid_t)-1;
  189. }
  190. // Get group id from option argument
  191. static char GetGid()
  192. {
  193. struct group *g;
  194. if ((g = getgrnam(optarg)))
  195. gid = g->gr_gid;
  196. else
  197. return GetNumericId(&gid, optarg);
  198. return 0;
  199. }
  200. // Get user id from option argument
  201. static char GetUid()
  202. {
  203. struct passwd *u;
  204. ////PORTABILITY: Assumes uid_t and gid_t are of same size (shouldn't be a problem)
  205. if ((u = getpwnam(optarg)))
  206. uid = u->pw_uid;
  207. else
  208. return GetNumericId((gid_t*)&uid, optarg);
  209. return 0;
  210. }
  211. #endif // _WIN32
  212. #endif //NO_USER_SWITCH
  213. #ifdef NO_HELP
  214. static __noreturn void usage()
  215. {
  216. printerrorf("Incorrect parameters\n\n");
  217. exit(!0);
  218. }
  219. #else // HELP
  220. static __noreturn void usage()
  221. {
  222. printerrorf("vlmcsd %s\n"
  223. "\nUsage:\n"
  224. " %s [ options ]\n\n"
  225. "Where:\n"
  226. #ifndef NO_CL_PIDS
  227. " -w <ePID> always use <ePID> for Windows\n"
  228. " -0 <ePID> always use <ePID> for Office2010\n"
  229. " -3 <ePID> always use <ePID> for Office2013\n"
  230. " -6 <ePID> always use <ePID> for Office2016\n"
  231. " -H <HwId> always use hardware Id <HwId>\n"
  232. #endif // NO_CL_PIDS
  233. #if !defined(_WIN32) && !defined(NO_USER_SWITCH)
  234. " -u <user> set uid to <user>\n"
  235. " -g <group> set gid to <group>\n"
  236. #endif // !defined(_WIN32) && !defined(NO_USER_SWITCH)
  237. #ifndef NO_RANDOM_EPID
  238. " -r 0|1|2\t\tset ePID randomization level (default 1)\n"
  239. " -C <LCID>\t\tuse fixed <LCID> in random ePIDs\n"
  240. #endif // NO_RANDOM_EPID
  241. #if !defined(NO_PRIVATE_IP_DETECT)
  242. #if HAVE_GETIFADDR
  243. " -o 0|1|2|3\t\tset protection level against clients with public IP addresses (default 0)\n"
  244. #else // !HAVE_GETIFADDR
  245. #ifndef USE_MSRPC
  246. " -o 0|2\t\tset protection level against clients with public IP addresses (default 0)\n"
  247. #else // USE_MSRPC
  248. " -o 0|2\t\tset protection level against clients with public IP addresses (default 0). Limited use with MS RPC\n"
  249. #endif // USE_MSRPC
  250. #endif // !HAVE_GETIFADDR
  251. #endif // !defined(NO_PRIVATE_IP_DETECT)
  252. #ifndef NO_SOCKETS
  253. #if !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
  254. " -L <address>[:<port>]\tlisten on IP address <address> with optional <port>\n"
  255. " -P <port>\t\tset TCP port <port> for subsequent -L statements (default 1688)\n"
  256. #if HAVE_FREEBIND
  257. " -F0, -F1\t\tdisable/enable binding to foreign IP addresses\n"
  258. #endif // HAVE_FREEBIND
  259. #else // defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)
  260. " -P <port>\t\tuse TCP port <port> (default 1688)\n"
  261. #endif // defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)
  262. #if !defined(NO_LIMIT) && !__minix__
  263. " -m <clients>\t\tHandle max. <clients> simultaneously (default no limit)\n"
  264. #endif // !defined(NO_LIMIT) && !__minix__
  265. #ifdef _NTSERVICE
  266. " -s install vlmcsd as an NT service. Ignores -e"
  267. #ifndef _WIN32
  268. ", -f and -D"
  269. #endif // _WIN32
  270. "\n"
  271. " -S remove vlmcsd service. Ignores all other options\n"
  272. " -U <username> run NT service as <username>. Must be used with -s\n"
  273. " -W <password> optional <password> for -U. Must be used with -s\n"
  274. #endif // _NTSERVICE
  275. #ifndef NO_LOG
  276. " -e log to stdout\n"
  277. #endif // NO_LOG
  278. #ifndef _WIN32 //
  279. " -D run in foreground\n"
  280. #else // _WIN32
  281. " -D does nothing. Provided for compatibility with POSIX versions only\n"
  282. #endif // _WIN32
  283. #endif // NO_SOCKETS
  284. #ifndef USE_MSRPC
  285. #if !defined(NO_TIMEOUT) && !__minix__
  286. " -t <seconds>\t\tdisconnect clients after <seconds> of inactivity (default 30)\n"
  287. #endif // !defined(NO_TIMEOUT) && !__minix__
  288. " -d\t\t\tdisconnect clients after each request\n"
  289. " -k\t\t\tdon't disconnect clients after each request (default)\n"
  290. " -N0, -N1\t\tdisable/enable NDR64\n"
  291. " -B0, -B1\t\tdisable/enable bind time feature negotiation\n"
  292. #endif // USE_MSRPC
  293. #ifndef NO_PID_FILE
  294. " -p <file> write pid to <file>\n"
  295. #endif // NO_PID_FILE
  296. #ifndef NO_INI_FILE
  297. " -i <file>\t\tuse config file <file>\n"
  298. #endif // NO_INI_FILE
  299. #ifndef NO_CUSTOM_INTERVALS
  300. " -R <interval> renew activation every <interval> (default 1w)\n"
  301. " -A <interval> retry activation every <interval> (default 2h)\n"
  302. #endif // NO_CUSTOM_INTERVALS
  303. #ifndef NO_LOG
  304. #ifndef _WIN32
  305. " -l syslog log to syslog\n"
  306. #endif // _WIN32
  307. " -l <file> log to <file>\n"
  308. " -T0, -T1\t\tdisable/enable logging with time and date (default -T1)\n"
  309. #ifndef NO_VERBOSE_LOG
  310. " -v\t\t\tlog verbose\n"
  311. " -q\t\t\tdon't log verbose (default)\n"
  312. #endif // NO_VERBOSE_LOG
  313. #endif // NO_LOG
  314. #ifndef NO_VERSION_INFORMATION
  315. " -V display version information and exit\n"
  316. #endif // NO_VERSION_INFORMATION
  317. ,
  318. Version, global_argv[0]);
  319. exit(!0);
  320. }
  321. #endif // HELP
  322. #ifndef NO_CUSTOM_INTERVALS
  323. // Convert time span strings (e.g. "2h", "5w") to minutes
  324. __pure static DWORD timeSpanString2Minutes(const char *const restrict argument)
  325. {
  326. char *unitId;
  327. long long val = vlmcsd_strtoll(argument, &unitId, 10);
  328. switch (toupper((int)*unitId))
  329. {
  330. case 0:
  331. case 'M':
  332. break;
  333. case 'H':
  334. val *= 60;
  335. break;
  336. case 'D':
  337. val *= 60 * 24;
  338. break;
  339. case 'W':
  340. val *= 60 * 24 * 7;
  341. break;
  342. case 'S':
  343. val /= 60;
  344. break;
  345. default:
  346. return 0;
  347. }
  348. if (val < 1) val = 1;
  349. if (val > UINT_MAX) val = UINT_MAX;
  350. return (DWORD)val;
  351. }
  352. #ifndef NO_INI_FILE
  353. __pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char *const restrict argument)
  354. {
  355. DWORD val = timeSpanString2Minutes(argument);
  356. if (!val)
  357. {
  358. IniFileErrorMessage = "Incorrect time span.";
  359. return FALSE;
  360. }
  361. *result = val;
  362. return TRUE;
  363. }
  364. #endif // NO_INI_FILE
  365. __pure static DWORD getTimeSpanFromCommandLine(const char *const restrict optarg, const char optchar)
  366. {
  367. long long val = timeSpanString2Minutes(optarg);
  368. if (!val)
  369. {
  370. printerrorf("Fatal: No valid time span specified in option -%c.\n", optchar);
  371. exit(!0);
  372. }
  373. return (DWORD)val;
  374. }
  375. #endif // NO_CUSTOM_INTERVALS
  376. #ifndef NO_INI_FILE
  377. static void ignoreIniFileParameter(uint_fast8_t iniFileParameterId)
  378. {
  379. uint_fast8_t i;
  380. for (i = 0; i < _countof(IniFileParameterList); i++)
  381. {
  382. if (IniFileParameterList[i].Id != iniFileParameterId) continue;
  383. IniFileParameterList[i].Id = 0;
  384. break;
  385. }
  386. }
  387. #else // NO_INI_FILE
  388. #define ignoreIniFileParameter(x)
  389. #endif // NO_INI_FILE
  390. #ifndef NO_INI_FILE
  391. static BOOL getIniFileArgumentBool(int_fast8_t *result, const char *const argument)
  392. {
  393. IniFileErrorMessage = "Argument must be true/on/yes/1 or false/off/no/0";
  394. return getArgumentBool(result, argument);
  395. }
  396. static BOOL getIniFileArgumentInt(unsigned int *result, const char *const argument, const unsigned int min, const unsigned int max)
  397. {
  398. unsigned int tempResult;
  399. if (!stringToInt(argument, min, max, &tempResult))
  400. {
  401. vlmcsd_snprintf(IniFileErrorBuffer, INIFILE_ERROR_BUFFERSIZE, "Must be integer between %u and %u", min, max);
  402. IniFileErrorMessage = IniFileErrorBuffer;
  403. return FALSE;
  404. }
  405. *result = tempResult;
  406. return TRUE;
  407. }
  408. static char* allocateStringArgument(const char *const argument)
  409. {
  410. char* result = (char*)vlmcsd_malloc(strlen(argument) + 1);
  411. strcpy(result, argument);
  412. return result;
  413. }
  414. static __pure int isControlCharOrSlash(const char c)
  415. {
  416. if ((unsigned char)c < '!') return !0;
  417. if (c == '/') return !0;
  418. return 0;
  419. }
  420. static void iniFileLineNextWord(const char **s)
  421. {
  422. while (**s && isspace((int)**s)) (*s)++;
  423. }
  424. static BOOL setHwIdFromIniFileLine(const char **s, const ProdListIndex_t index)
  425. {
  426. iniFileLineNextWord(s);
  427. if (**s == '/')
  428. {
  429. if (KmsResponseParameters[index].HwId) return TRUE;
  430. BYTE* HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6 *)0)->HwId));
  431. hex2bin(HwId, *s + 1, sizeof(((RESPONSE_V6 *)0)->HwId));
  432. KmsResponseParameters[index].HwId = HwId;
  433. }
  434. return TRUE;
  435. }
  436. static BOOL setEpidFromIniFileLine(const char **s, const ProdListIndex_t index)
  437. {
  438. iniFileLineNextWord(s);
  439. const char *savedPosition = *s;
  440. uint_fast16_t i;
  441. for (i = 0; !isControlCharOrSlash(**s); i++)
  442. {
  443. if (utf8_to_ucs2_char((const unsigned char*)*s, (const unsigned char**)s) == (WCHAR)~0)
  444. {
  445. return FALSE;
  446. }
  447. }
  448. if (i < 1 || i >= PID_BUFFER_SIZE) return FALSE;
  449. if (KmsResponseParameters[index].Epid) return TRUE;
  450. size_t size = *s - savedPosition + 1;
  451. char* epidbuffer = (char*)vlmcsd_malloc(size);
  452. memcpy(epidbuffer, savedPosition, size - 1);
  453. epidbuffer[size - 1] = 0;
  454. KmsResponseParameters[index].Epid = epidbuffer;
  455. #ifndef NO_LOG
  456. KmsResponseParameters[index].EpidSource = fn_ini;
  457. #endif //NO_LOG
  458. return TRUE;
  459. }
  460. static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
  461. {
  462. unsigned int result;
  463. BOOL success = TRUE;
  464. const char *s = (const char*)iniarg;
  465. switch (id)
  466. {
  467. case INI_PARAM_WINDOWS:
  468. setEpidFromIniFileLine(&s, EPID_INDEX_WINDOWS);
  469. setHwIdFromIniFileLine(&s, EPID_INDEX_WINDOWS);
  470. break;
  471. case INI_PARAM_OFFICE2010:
  472. setEpidFromIniFileLine(&s, EPID_INDEX_OFFICE2010);
  473. setHwIdFromIniFileLine(&s, EPID_INDEX_OFFICE2010);
  474. break;
  475. case INI_PARAM_OFFICE2013:
  476. setEpidFromIniFileLine(&s, EPID_INDEX_OFFICE2013);
  477. setHwIdFromIniFileLine(&s, EPID_INDEX_OFFICE2013);
  478. break;
  479. case INI_PARAM_OFFICE2016:
  480. setEpidFromIniFileLine(&s, EPID_INDEX_OFFICE2016);
  481. setHwIdFromIniFileLine(&s, EPID_INDEX_OFFICE2016);
  482. break;
  483. # if !defined(NO_USER_SWITCH) && !defined(_WIN32)
  484. case INI_PARAM_GID:
  485. {
  486. struct group *g;
  487. IniFileErrorMessage = "Invalid group id or name";
  488. if (!(gname = allocateStringArgument(iniarg))) return FALSE;
  489. if ((g = getgrnam(iniarg)))
  490. gid = g->gr_gid;
  491. else
  492. success = !GetNumericId(&gid, iniarg);
  493. break;
  494. }
  495. case INI_PARAM_UID:
  496. {
  497. struct passwd *p;
  498. IniFileErrorMessage = "Invalid user id or name";
  499. if (!(uname = allocateStringArgument(iniarg))) return FALSE;
  500. if ((p = getpwnam(iniarg)))
  501. uid = p->pw_uid;
  502. else
  503. success = !GetNumericId(&uid, iniarg);
  504. break;
  505. }
  506. # endif // !defined(NO_USER_SWITCH) && !defined(_WIN32)
  507. # ifndef NO_RANDOM_EPID
  508. case INI_PARAM_LCID:
  509. success = getIniFileArgumentInt(&result, iniarg, 0, 32767);
  510. if (success) Lcid = (uint16_t)result;
  511. break;
  512. case INI_PARAM_RANDOMIZATION_LEVEL:
  513. success = getIniFileArgumentInt(&result, iniarg, 0, 2);
  514. if (success) RandomizationLevel = (int_fast8_t)result;
  515. break;
  516. # endif // NO_RANDOM_EPID
  517. # if (defined(USE_MSRPC) || defined(SIMPLE_SOCKETS) || defined(HAVE_GETIFADDR)) && !defined(NO_SOCKETS)
  518. case INI_PARAM_PORT:
  519. defaultport = allocateStringArgument(iniarg);
  520. break;
  521. # endif // (defined(USE_MSRPC) || defined(SIMPLE_SOCKETS) || defined(HAVE_GETIFADDR)) && !defined(NO_SOCKETS)
  522. # if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
  523. case INI_PARAM_LISTEN:
  524. maxsockets++;
  525. return TRUE;
  526. # endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
  527. # if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
  528. case INI_PARAM_MAX_WORKERS:
  529. # ifdef USE_MSRPC
  530. success = getIniFileArgumentInt(&MaxTasks, iniarg, 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT);
  531. # else // !USE_MSRPC
  532. success = getIniFileArgumentInt(&MaxTasks, iniarg, 1, SEM_VALUE_MAX);
  533. # endif // !USE_MSRPC
  534. break;
  535. # endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
  536. # ifndef NO_PID_FILE
  537. case INI_PARAM_PID_FILE:
  538. fn_pid = allocateStringArgument(iniarg);
  539. break;
  540. # endif // NO_PID_FILE
  541. # ifndef NO_LOG
  542. case INI_PARAM_LOG_FILE:
  543. fn_log = allocateStringArgument(iniarg);
  544. break;
  545. case INI_PARAM_LOG_DATE_AND_TIME:
  546. success = getIniFileArgumentBool(&LogDateAndTime, iniarg);
  547. break;
  548. # ifndef NO_VERBOSE_LOG
  549. case INI_PARAM_LOG_VERBOSE:
  550. success = getIniFileArgumentBool(&logverbose, iniarg);
  551. break;
  552. # endif // NO_VERBOSE_LOG
  553. # endif // NO_LOG
  554. # ifndef NO_CUSTOM_INTERVALS
  555. case INI_PARAM_ACTIVATION_INTERVAL:
  556. success = getTimeSpanFromIniFile(&VLActivationInterval, iniarg);
  557. break;
  558. case INI_PARAM_RENEWAL_INTERVAL:
  559. success = getTimeSpanFromIniFile(&VLRenewalInterval, iniarg);
  560. break;
  561. # endif // NO_CUSTOM_INTERVALS
  562. # ifndef USE_MSRPC
  563. # if !defined(NO_TIMEOUT) && !__minix__
  564. case INI_PARAM_CONNECTION_TIMEOUT:
  565. success = getIniFileArgumentInt(&result, iniarg, 1, 600);
  566. if (success) ServerTimeout = (DWORD)result;
  567. break;
  568. # endif // !defined(NO_TIMEOUT) && !__minix__
  569. case INI_PARAM_DISCONNECT_IMMEDIATELY:
  570. success = getIniFileArgumentBool(&DisconnectImmediately, iniarg);
  571. break;
  572. case INI_PARAM_RPC_NDR64:
  573. success = getIniFileArgumentBool(&UseRpcNDR64, iniarg);
  574. break;
  575. case INI_PARAM_RPC_BTFN:
  576. success = getIniFileArgumentBool(&UseRpcBTFN, iniarg);
  577. break;
  578. # endif // USE_MSRPC
  579. # if HAVE_FREEBIND
  580. case INI_PARAM_FREEBIND:
  581. success = getIniFileArgumentBool(&freebind, iniarg);
  582. break;
  583. # endif // HAVE_FREEBIND
  584. # if !defined(NO_PRIVATE_IP_DETECT)
  585. case INI_PARAM_PUBLIC_IP_PROTECTION_LEVEL:
  586. success = getIniFileArgumentInt(&PublicIPProtectionLevel, iniarg, 0, 3);
  587. # if !HAVE_GETIFADDR
  588. if (PublicIPProtectionLevel & 1)
  589. {
  590. IniFileErrorMessage = "Must be 0 or 2";
  591. success = FALSE;
  592. }
  593. # endif // !HAVE_GETIFADDR
  594. break;
  595. # endif // !defined(NO_PRIVATE_IP_DETECT)
  596. default:
  597. return FALSE;
  598. }
  599. return success;
  600. }
  601. static BOOL getIniFileArgument(const char **s)
  602. {
  603. while (!isspace((int)**s) && **s != '=' && **s) (*s)++;
  604. iniFileLineNextWord(s);
  605. if (*((*s)++) != '=')
  606. {
  607. IniFileErrorMessage = "'=' required after keyword.";
  608. return FALSE;
  609. }
  610. iniFileLineNextWord(s);
  611. if (!**s)
  612. {
  613. IniFileErrorMessage = "missing argument after '='.";
  614. return FALSE;
  615. }
  616. return TRUE;
  617. }
  618. static BOOL handleIniFileParameter(const char *s)
  619. {
  620. uint_fast8_t i;
  621. for (i = 0; i < _countof(IniFileParameterList); i++)
  622. {
  623. if (strncasecmp(IniFileParameterList[i].Name, s, strlen(IniFileParameterList[i].Name))) continue;
  624. if (!IniFileParameterList[i].Id) return TRUE;
  625. if (!getIniFileArgument(&s)) return FALSE;
  626. return setIniFileParameter(IniFileParameterList[i].Id, s);
  627. }
  628. IniFileErrorMessage = "Unknown keyword.";
  629. return FALSE;
  630. }
  631. #if !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
  632. static BOOL setupListeningSocketsFromIniFile(const char *s)
  633. {
  634. if (!maxsockets) return TRUE;
  635. if (strncasecmp("Listen", s, 6)) return TRUE;
  636. if (!getIniFileArgument(&s)) return TRUE;
  637. vlmcsd_snprintf(IniFileErrorBuffer, INIFILE_ERROR_BUFFERSIZE, "Cannot listen on %s.", s);
  638. IniFileErrorMessage = IniFileErrorBuffer;
  639. return addListeningSocket(s);
  640. }
  641. #endif // !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
  642. static BOOL readIniFile(const uint_fast8_t pass)
  643. {
  644. char line[256];
  645. const char *s;
  646. unsigned int lineNumber;
  647. uint_fast8_t lineParseError;
  648. FILE *restrict f;
  649. BOOL result = TRUE;
  650. IniFileErrorBuffer = (char*)vlmcsd_malloc(INIFILE_ERROR_BUFFERSIZE);
  651. if (!(f = fopen(fn_ini, "r"))) return FALSE;
  652. for (lineNumber = 1; (s = fgets(line, sizeof(line), f)); lineNumber++)
  653. {
  654. line[strlen(line) - 1] = 0;
  655. iniFileLineNextWord(&s);
  656. if (*s == ';' || *s == '#' || !*s) continue;
  657. # ifndef NO_SOCKETS
  658. if (pass == INI_FILE_PASS_1)
  659. # endif // NO_SOCKETS
  660. {
  661. if (handleIniFileParameter(s)) continue;
  662. lineParseError = TRUE;/*!checkGuidInIniFileLine(&s, &appIndex) ||
  663. !setEpidFromIniFileLine(&s, appIndex) ||
  664. !setHwIdFromIniFileLine(&s, appIndex);*/
  665. }
  666. # if !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
  667. else if (pass == INI_FILE_PASS_2)
  668. {
  669. lineParseError = !setupListeningSocketsFromIniFile(s);
  670. }
  671. else
  672. {
  673. return FALSE;
  674. }
  675. # endif // !defined(NO_SOCKETS) && && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
  676. if (lineParseError)
  677. {
  678. printerrorf("Warning: %s line %u: \"%s\". %s\n", fn_ini, lineNumber, line, IniFileErrorMessage);
  679. continue;
  680. }
  681. }
  682. if (ferror(f)) result = FALSE;
  683. free(IniFileErrorBuffer);
  684. fclose(f);
  685. # if !defined(NO_SOCKETS) && !defined(NO_LOG)
  686. if (pass == INI_FILE_PASS_1 && !InetdMode && result)
  687. {
  688. # ifdef _NTSERVICE
  689. if (!installService)
  690. # endif // _NTSERVICE
  691. logger("Read ini file %s\n", fn_ini);
  692. }
  693. # endif // !defined(NO_SOCKETS) && !defined(NO_LOG)
  694. return result;
  695. }
  696. #endif // NO_INI_FILE
  697. #if !defined(NO_SOCKETS)
  698. #if !defined(_WIN32)
  699. #if !defined(NO_SIGHUP)
  700. static void exec_self(char** argv)
  701. {
  702. # if __linux__ && defined(USE_AUXV)
  703. char *execname_ptr = (char*)getauxval(AT_EXECFN);
  704. if (execname_ptr) execv(execname_ptr, argv);
  705. # elif (__linux__ || __CYGWIN__) && !defined(NO_PROCFS)
  706. execv(realpath("/proc/self/exe", NULL), argv);
  707. # elif (__FreeBSD__) && !defined(NO_PROCFS)
  708. int mib[4];
  709. mib[0] = CTL_KERN;
  710. mib[1] = KERN_PROC;
  711. mib[2] = KERN_PROC_PATHNAME;
  712. mib[3] = -1;
  713. char path[PATH_MAX + 1];
  714. size_t cb = sizeof(path);
  715. if (!sysctl(mib, 4, path, &cb, NULL, 0)) execv(path, argv);
  716. # elif (__DragonFly__) && !defined(NO_PROCFS)
  717. execv(realpath("/proc/curproc/file", NULL), argv);
  718. # elif __NetBSD__ && !defined(NO_PROCFS)
  719. execv(realpath("/proc/curproc/exe", NULL), argv);
  720. # elif __sun__
  721. const char* exename = getexecname();
  722. if (exename) execv(exename, argv);
  723. # elif __APPLE__
  724. char path[PATH_MAX + 1];
  725. uint32_t size = sizeof(path);
  726. if (_NSGetExecutablePath(path, &size) == 0) execv(path, argv);
  727. # else
  728. execvp(argv[0], argv);
  729. # endif
  730. }
  731. static void HangupHandler(const int signal_unused)
  732. {
  733. int i;
  734. int_fast8_t daemonize_protection = TRUE;
  735. CARGV argv_in = multi_argv == NULL ? global_argv : multi_argv;
  736. int argc_in = multi_argc == 0 ? global_argc : multi_argc;
  737. const char** argv_out = (const char**)vlmcsd_malloc((argc_in + 2) * sizeof(char**));
  738. for (i = 0; i < argc_in; i++)
  739. {
  740. if (!strcmp(argv_in[i], "-Z")) daemonize_protection = FALSE;
  741. argv_out[i] = argv_in[i];
  742. }
  743. argv_out[argc_in] = argv_out[argc_in + 1] = NULL;
  744. if (daemonize_protection) argv_out[argc_in] = (char*) "-Z";
  745. exec_self((char**)argv_out);
  746. # ifndef NO_LOG
  747. logger("Fatal: Unable to restart on SIGHUP: %s\n", strerror(errno));
  748. # endif
  749. # ifndef NO_PID_FILE
  750. if (fn_pid) unlink(fn_pid);
  751. # endif // NO_PID_FILE
  752. exit(errno);
  753. }
  754. #endif // NO_SIGHUP
  755. static void terminationHandler(const int signal_unused)
  756. {
  757. cleanup();
  758. exit(0);
  759. }
  760. #if defined(CHILD_HANDLER) || __minix__
  761. static void childHandler(const int signal)
  762. {
  763. waitpid(-1, NULL, WNOHANG);
  764. }
  765. #endif // defined(CHILD_HANDLER) || __minix__
  766. static int daemonizeAndSetSignalAction()
  767. {
  768. struct sigaction sa;
  769. sigemptyset(&sa.sa_mask);
  770. # ifndef NO_LOG
  771. if (!nodaemon) if (daemon(!0, logstdout))
  772. # else // NO_LOG
  773. if (!nodaemon) if (daemon(!0, 0))
  774. # endif // NO_LOG
  775. {
  776. printerrorf("Fatal: Could not daemonize to background.\n");
  777. return(errno);
  778. }
  779. if (!InetdMode)
  780. {
  781. # ifndef USE_THREADS
  782. # if defined(CHILD_HANDLER) || __minix__
  783. sa.sa_handler = childHandler;
  784. # else // !(defined(CHILD_HANDLER) || __minix__)
  785. sa.sa_handler = SIG_IGN;
  786. # endif // !(defined(CHILD_HANDLER) || __minix__)
  787. sa.sa_flags = SA_NOCLDWAIT;
  788. if (sigaction(SIGCHLD, &sa, NULL))
  789. return(errno);
  790. # endif // !USE_THREADS
  791. sa.sa_handler = terminationHandler;
  792. sa.sa_flags = 0;
  793. sigaction(SIGINT, &sa, NULL);
  794. sigaction(SIGTERM, &sa, NULL);
  795. # ifndef NO_SIGHUP
  796. sa.sa_handler = HangupHandler;
  797. sa.sa_flags = SA_NODEFER;
  798. sigaction(SIGHUP, &sa, NULL);
  799. # endif // NO_SIGHUP
  800. }
  801. return 0;
  802. }
  803. #else // _WIN32
  804. static BOOL terminationHandler(const DWORD fdwCtrlType)
  805. {
  806. // What a lame substitute for Unix signal handling
  807. switch (fdwCtrlType)
  808. {
  809. case CTRL_C_EVENT:
  810. case CTRL_CLOSE_EVENT:
  811. case CTRL_BREAK_EVENT:
  812. case CTRL_LOGOFF_EVENT:
  813. case CTRL_SHUTDOWN_EVENT:
  814. cleanup();
  815. exit(0);
  816. default:
  817. return FALSE;
  818. }
  819. }
  820. static DWORD daemonizeAndSetSignalAction()
  821. {
  822. if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)terminationHandler, TRUE))
  823. {
  824. #ifndef NO_LOG
  825. DWORD rc = GetLastError();
  826. logger("Warning: Could not register Windows signal handler: Error %u\n", rc);
  827. #endif // NO_LOG
  828. }
  829. return ERROR_SUCCESS;
  830. }
  831. #endif // _WIN32
  832. #endif // !defined(NO_SOCKETS)
  833. // Workaround for Cygwin fork bug (only affects cygwin processes that are Windows services)
  834. // Best is to compile for Cygwin with threads. fork() is slow and unreliable on Cygwin
  835. #if !defined(NO_INI_FILE) || !defined(NO_LOG) || !defined(NO_CL_PIDS)
  836. __pure static char* getCommandLineArg(char *const restrict optarg)
  837. {
  838. # if !defined (__CYGWIN__) || defined(USE_THREADS) || defined(NO_SOCKETS)
  839. return optarg;
  840. # else
  841. if (!IsNTService) return optarg;
  842. return allocateStringArgument(optarg);
  843. # endif
  844. }
  845. #endif // !defined(NO_INI_FILE) || !defined(NO_LOG) || !defined(NO_CL_PIDS)
  846. static void parseGeneralArguments() {
  847. int o;
  848. #ifndef NO_CL_PIDS
  849. BYTE* HwId;
  850. #endif // NO_CL_PIDS
  851. for (opterr = 0; (o = getopt(global_argc, (char* const*)global_argv, (const char*)optstring)) > 0; ) switch (o)
  852. {
  853. # if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
  854. case 'Z':
  855. IsRestarted = TRUE;
  856. nodaemon = TRUE;
  857. break;
  858. # endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
  859. # ifndef NO_CL_PIDS
  860. case 'w':
  861. KmsResponseParameters[EPID_INDEX_WINDOWS].Epid = getCommandLineArg(optarg);
  862. # ifndef NO_LOG
  863. KmsResponseParameters[EPID_INDEX_WINDOWS].EpidSource = "command line";
  864. # endif // NO_LOG
  865. break;
  866. case '0':
  867. KmsResponseParameters[EPID_INDEX_OFFICE2010].Epid = getCommandLineArg(optarg);
  868. # ifndef NO_LOG
  869. KmsResponseParameters[EPID_INDEX_OFFICE2010].EpidSource = "command line";
  870. # endif // NO_LOG
  871. break;
  872. case '3':
  873. KmsResponseParameters[EPID_INDEX_OFFICE2013].Epid = getCommandLineArg(optarg);
  874. # ifndef NO_LOG
  875. KmsResponseParameters[EPID_INDEX_OFFICE2013].EpidSource = "command line";
  876. # endif // NO_LOG
  877. break;
  878. case '6':
  879. KmsResponseParameters[EPID_INDEX_OFFICE2016].Epid = getCommandLineArg(optarg);
  880. # ifndef NO_LOG
  881. KmsResponseParameters[EPID_INDEX_OFFICE2016].EpidSource = "command line";
  882. # endif // NO_LOG
  883. break;
  884. case 'H':
  885. HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6 *)0)->HwId));
  886. hex2bin(HwId, optarg, sizeof(((RESPONSE_V6 *)0)->HwId));
  887. KmsResponseParameters[EPID_INDEX_WINDOWS].HwId =
  888. KmsResponseParameters[EPID_INDEX_OFFICE2010].HwId =
  889. KmsResponseParameters[EPID_INDEX_OFFICE2013].HwId =
  890. KmsResponseParameters[EPID_INDEX_OFFICE2016].HwId = HwId;
  891. break;
  892. # endif // NO_CL_PIDS
  893. # ifndef NO_SOCKETS
  894. case 'P':
  895. ignoreIniFileParameter(INI_PARAM_PORT);
  896. # if !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
  897. ignoreIniFileParameter(INI_PARAM_LISTEN);
  898. # else
  899. defaultport = optarg;
  900. # endif // !SIMPLE_SOCKETS
  901. break;
  902. # if !defined(NO_LIMIT) && !__minix__
  903. case 'm':
  904. # ifdef USE_MSRPC
  905. MaxTasks = getOptionArgumentInt(o, 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT);
  906. # else // !USE_MSRPC
  907. MaxTasks = getOptionArgumentInt((char)o, 1, SEM_VALUE_MAX);
  908. # endif // !USE_MSRPC
  909. ignoreIniFileParameter(INI_PARAM_MAX_WORKERS);
  910. break;
  911. # endif // !defined(NO_LIMIT) && !__minix__
  912. # endif // NO_SOCKETS
  913. # if !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC)
  914. case 't':
  915. ServerTimeout = getOptionArgumentInt((char)o, 1, 600);
  916. ignoreIniFileParameter(INI_PARAM_CONNECTION_TIMEOUT);
  917. break;
  918. # endif // !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC)
  919. # ifndef NO_PID_FILE
  920. case 'p':
  921. fn_pid = getCommandLineArg(optarg);
  922. ignoreIniFileParameter(INI_PARAM_PID_FILE);
  923. break;
  924. # endif
  925. # ifndef NO_INI_FILE
  926. case 'i':
  927. fn_ini = getCommandLineArg(optarg);
  928. if (!strcmp(fn_ini, "-")) fn_ini = NULL;
  929. break;
  930. # endif
  931. # ifndef NO_LOG
  932. case 'T':
  933. if (!getArgumentBool(&LogDateAndTime, optarg)) usage();
  934. ignoreIniFileParameter(INI_PARAM_LOG_DATE_AND_TIME);
  935. break;
  936. case 'l':
  937. fn_log = getCommandLineArg(optarg);
  938. ignoreIniFileParameter(INI_PARAM_LOG_FILE);
  939. break;
  940. # ifndef NO_VERBOSE_LOG
  941. case 'v':
  942. case 'q':
  943. logverbose = o == 'v';
  944. ignoreIniFileParameter(INI_PARAM_LOG_VERBOSE);
  945. break;
  946. # endif // NO_VERBOSE_LOG
  947. # endif // NO_LOG
  948. # if !defined(NO_PRIVATE_IP_DETECT)
  949. case 'o':
  950. ignoreIniFileParameter(INI_PARAM_PUBLIC_IP_PROTECTION_LEVEL);
  951. PublicIPProtectionLevel = getOptionArgumentInt((char)o, 0, 3);
  952. # if !HAVE_GETIFADDR
  953. if (PublicIPProtectionLevel & 1) usage();
  954. # endif // !HAVE_GETIFADDR
  955. break;
  956. # endif // !defined(NO_PRIVATE_IP_DETECT)
  957. # ifndef NO_SOCKETS
  958. # if !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
  959. case 'L':
  960. maxsockets++;
  961. ignoreIniFileParameter(INI_PARAM_LISTEN);
  962. break;
  963. # if HAVE_FREEBIND
  964. case 'F':
  965. if (!getArgumentBool(&freebind, optarg)) usage();
  966. ignoreIniFileParameter(INI_PARAM_FREEBIND);
  967. break;
  968. # endif // HAVE_FREEBIND
  969. # endif // !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
  970. # ifdef _NTSERVICE
  971. case 'U':
  972. ServiceUser = optarg;
  973. break;
  974. case 'W':
  975. ServicePassword = optarg;
  976. break;
  977. case 's':
  978. # ifndef USE_MSRPC
  979. if (InetdMode) usage();
  980. # endif // USE_MSRPC
  981. if (!IsNTService) installService = 1; // Install
  982. break;
  983. case 'S':
  984. if (!IsNTService) installService = 2; // Remove
  985. break;
  986. # endif // _NTSERVICE
  987. case 'D':
  988. # ifndef _WIN32
  989. nodaemon = 1;
  990. # else // _WIN32
  991. # ifdef _PEDANTIC
  992. printerrorf("Warning: Option -D has no effect in the Windows version of vlmcsd.\n");
  993. # endif // _PEDANTIC
  994. # endif // _WIN32
  995. break;
  996. # ifndef NO_LOG
  997. case 'e':
  998. logstdout = 1;
  999. break;
  1000. # endif // NO_LOG
  1001. # endif // NO_SOCKETS
  1002. # ifndef NO_RANDOM_EPID
  1003. case 'r':
  1004. RandomizationLevel = (int_fast8_t)getOptionArgumentInt((char)o, 0, 2);
  1005. ignoreIniFileParameter(INI_PARAM_RANDOMIZATION_LEVEL);
  1006. break;
  1007. case 'C':
  1008. Lcid = (uint16_t)getOptionArgumentInt((char)o, 0, 32767);
  1009. ignoreIniFileParameter(INI_PARAM_LCID);
  1010. # ifdef _PEDANTIC
  1011. if (!IsValidLcid(Lcid))
  1012. {
  1013. printerrorf("Warning: %s is not a valid LCID.\n", optarg);
  1014. }
  1015. # endif // _PEDANTIC
  1016. break;
  1017. # endif // NO_RANDOM_PID
  1018. # if !defined(NO_USER_SWITCH) && !defined(_WIN32)
  1019. case 'g':
  1020. gname = optarg;
  1021. ignoreIniFileParameter(INI_PARAM_GID);
  1022. # ifndef NO_SIGHUP
  1023. if (!IsRestarted)
  1024. # endif // NO_SIGHUP
  1025. if (GetGid())
  1026. {
  1027. printerrorf("Fatal: %s for %s failed: %s\n", "setgid", gname, strerror(errno));
  1028. exit(errno);
  1029. }
  1030. break;
  1031. case 'u':
  1032. uname = optarg;
  1033. ignoreIniFileParameter(INI_PARAM_UID);
  1034. # ifndef NO_SIGHUP
  1035. if (!IsRestarted)
  1036. # endif // NO_SIGHUP
  1037. if (GetUid())
  1038. {
  1039. printerrorf("Fatal: %s for %s failed: %s\n", "setuid", uname, strerror(errno));
  1040. exit(errno);
  1041. }
  1042. break;
  1043. # endif // NO_USER_SWITCH && !_WIN32
  1044. # ifndef NO_CUSTOM_INTERVALS
  1045. case 'R':
  1046. VLRenewalInterval = getTimeSpanFromCommandLine(optarg, (char)o);
  1047. ignoreIniFileParameter(INI_PARAM_RENEWAL_INTERVAL);
  1048. break;
  1049. case 'A':
  1050. VLActivationInterval = getTimeSpanFromCommandLine(optarg, (char)o);
  1051. ignoreIniFileParameter(INI_PARAM_ACTIVATION_INTERVAL);
  1052. break;
  1053. # endif // NO_CUSTOM_INTERVALS
  1054. # ifndef USE_MSRPC
  1055. case 'd':
  1056. case 'k':
  1057. DisconnectImmediately = o == 'd';
  1058. ignoreIniFileParameter(INI_PARAM_DISCONNECT_IMMEDIATELY);
  1059. break;
  1060. case 'N':
  1061. if (!getArgumentBool(&UseRpcNDR64, optarg)) usage();
  1062. ignoreIniFileParameter(INI_PARAM_RPC_NDR64);
  1063. break;
  1064. case 'B':
  1065. if (!getArgumentBool(&UseRpcBTFN, optarg)) usage();
  1066. ignoreIniFileParameter(INI_PARAM_RPC_BTFN);
  1067. break;
  1068. # endif // !USE_MSRPC
  1069. # ifndef NO_VERSION_INFORMATION
  1070. case 'V':
  1071. # ifdef _NTSERVICE
  1072. if (IsNTService) break;
  1073. # endif
  1074. # if defined(__s390__) && !defined(__zarch__) && !defined(__s390x__)
  1075. printf("vlmcsd %s %i-bit\n", Version, sizeof(void*) == 4 ? 31 : (int)sizeof(void*) << 3);
  1076. # else
  1077. printf("vlmcsd %s %i-bit\n", Version, (int)sizeof(void*) << 3);
  1078. # endif // defined(__s390__) && !defined(__zarch__) && !defined(__s390x__)
  1079. printPlatform();
  1080. printCommonFlags();
  1081. printServerFlags();
  1082. exit(0);
  1083. # endif // NO_VERSION_INFORMATION
  1084. default:
  1085. usage();
  1086. }
  1087. // Do not allow non-option arguments
  1088. if (optind != global_argc)
  1089. usage();
  1090. # ifdef _NTSERVICE
  1091. // -U and -W must be used with -s
  1092. if ((ServiceUser || *ServicePassword) && installService != 1) usage();
  1093. # endif // _NTSERVICE
  1094. }
  1095. #if !defined(NO_PID_FILE)
  1096. static void writePidFile()
  1097. {
  1098. # ifndef NO_SIGHUP
  1099. if (IsRestarted) return;
  1100. # endif // NO_SIGHUP
  1101. if (fn_pid && !InetdMode)
  1102. {
  1103. FILE *_f = fopen(fn_pid, "w");
  1104. if (_f)
  1105. {
  1106. # if _MSC_VER
  1107. fprintf(_f, "%u", (unsigned int)GetCurrentProcessId());
  1108. # else
  1109. fprintf(_f, "%u", (unsigned int)getpid());
  1110. # endif
  1111. fclose(_f);
  1112. }
  1113. # ifndef NO_LOG
  1114. else
  1115. {
  1116. logger("Warning: Cannot write pid file '%s'. %s.\n", fn_pid, strerror(errno));
  1117. }
  1118. # endif // NO_LOG
  1119. }
  1120. }
  1121. #else
  1122. #define writePidFile()
  1123. #endif // !defined(NO_PID_FILE)
  1124. #if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
  1125. void cleanup()
  1126. {
  1127. if (!InetdMode)
  1128. {
  1129. # ifndef NO_PID_FILE
  1130. if (fn_pid) vlmcsd_unlink(fn_pid);
  1131. # endif // NO_PID_FILE
  1132. closeAllListeningSockets();
  1133. # if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !defined(_WIN32) && !__minix__
  1134. sem_unlink("/vlmcsd");
  1135. # if !defined(USE_THREADS) && !defined(CYGWIN)
  1136. if (shmid >= 0)
  1137. {
  1138. if (Semaphore != (sem_t*)-1) shmdt(Semaphore);
  1139. shmctl(shmid, IPC_RMID, NULL);
  1140. }
  1141. # endif // !defined(USE_THREADS) && !defined(CYGWIN)
  1142. # endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !defined(_WIN32) && !__minix__
  1143. # ifndef NO_LOG
  1144. logger("vlmcsd %s was shutdown\n", Version);
  1145. # endif // NO_LOG
  1146. }
  1147. }
  1148. #elif defined(USE_MSRPC)
  1149. void cleanup()
  1150. {
  1151. # ifndef NO_PID_FILE
  1152. if (fn_pid) unlink(fn_pid);
  1153. # endif // NO_PID_FILE
  1154. # ifndef NO_LOG
  1155. logger("vlmcsd %s was shutdown\n", Version);
  1156. # endif // NO_LOG
  1157. }
  1158. #else // Neither Sockets nor RPC
  1159. __pure void cleanup() {}
  1160. #endif // Neither Sockets nor RPC
  1161. #if !defined(USE_MSRPC) && !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
  1162. // Get a semaphore for limiting the maximum concurrent tasks
  1163. static void allocateSemaphore(void)
  1164. {
  1165. # ifdef USE_THREADS
  1166. # define sharemode 0
  1167. # else
  1168. # define sharemode 1
  1169. # endif
  1170. # ifndef _WIN32
  1171. sem_unlink("/vlmcsd");
  1172. # endif
  1173. if (MaxTasks < SEM_VALUE_MAX && !InetdMode)
  1174. {
  1175. # ifndef _WIN32
  1176. # if !defined(USE_THREADS) && !defined(CYGWIN)
  1177. if ((Semaphore = sem_open("/vlmcsd", O_CREAT /*| O_EXCL*/, 0700, MaxTasks)) == SEM_FAILED) // fails on many systems
  1178. {
  1179. // We didn't get a named Semaphore (/dev/shm on Linux) so let's try our own shared page
  1180. if (
  1181. (shmid = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600)) < 0 ||
  1182. (Semaphore = (sem_t*)shmat(shmid, NULL, 0)) == (sem_t*)-1 ||
  1183. sem_init(Semaphore, 1, MaxTasks) < 0
  1184. )
  1185. {
  1186. int errno_save = errno;
  1187. if (Semaphore != (sem_t*)-1) shmdt(Semaphore);
  1188. if (shmid >= 0) shmctl(shmid, IPC_RMID, NULL);
  1189. printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno_save));
  1190. MaxTasks = SEM_VALUE_MAX;
  1191. }
  1192. }
  1193. # else // THREADS or CYGWIN
  1194. Semaphore = (sem_t*)vlmcsd_malloc(sizeof(sem_t));
  1195. if (sem_init(Semaphore, sharemode, MaxTasks) < 0) // sem_init is not implemented on Darwin (returns ENOSYS)
  1196. {
  1197. free(Semaphore);
  1198. if ((Semaphore = sem_open("/vlmcsd", O_CREAT /*| O_EXCL*/, 0700, MaxTasks)) == SEM_FAILED)
  1199. {
  1200. printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno));
  1201. MaxTasks = SEM_VALUE_MAX;
  1202. }
  1203. }
  1204. # endif // THREADS or CYGWIN
  1205. # else // _WIN32
  1206. if (!(Semaphore = CreateSemaphoreA(NULL, MaxTasks, MaxTasks, NULL)))
  1207. {
  1208. printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(GetLastError()));
  1209. MaxTasks = SEM_VALUE_MAX;
  1210. }
  1211. # endif // _WIN32
  1212. }
  1213. }
  1214. #endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
  1215. #if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
  1216. int setupListeningSockets()
  1217. {
  1218. int o;
  1219. # if HAVE_GETIFADDR
  1220. char** privateIPList = NULL;
  1221. int numPrivateIPs = 0;
  1222. if (PublicIPProtectionLevel & 1) getPrivateIPAddresses(&numPrivateIPs, &privateIPList);
  1223. uint_fast8_t allocsockets = maxsockets ? (maxsockets + numPrivateIPs) : ((PublicIPProtectionLevel & 1) ? numPrivateIPs : 2);
  1224. # else // !HAVE_GETIFADDR
  1225. uint_fast8_t allocsockets = maxsockets ? maxsockets : 2;
  1226. # endif // !HAVE_GETIFADDR
  1227. SocketList = (SOCKET*)vlmcsd_malloc((size_t)allocsockets * sizeof(SOCKET));
  1228. int_fast8_t haveIPv4Stack = checkProtocolStack(AF_INET);
  1229. int_fast8_t haveIPv6Stack = checkProtocolStack(AF_INET6);
  1230. // Reset getopt since we've alread used it
  1231. optReset();
  1232. for (opterr = 0; (o = getopt(global_argc, (char* const*)global_argv, (const char*)optstring)) > 0; ) switch (o)
  1233. {
  1234. case 'P':
  1235. defaultport = optarg;
  1236. break;
  1237. case 'L':
  1238. addListeningSocket(optarg);
  1239. break;
  1240. default:
  1241. break;
  1242. }
  1243. # ifndef NO_INI_FILE
  1244. if (maxsockets && !numsockets)
  1245. {
  1246. if (fn_ini && !readIniFile(INI_FILE_PASS_2))
  1247. {
  1248. # ifdef INI_FILE
  1249. if (strcmp(fn_ini, INI_FILE))
  1250. # endif // INI_FILE
  1251. printerrorf("Warning: Can't read %s: %s\n", fn_ini, strerror(errno));
  1252. }
  1253. }
  1254. # endif
  1255. # if HAVE_GETIFADDR
  1256. if (PublicIPProtectionLevel & 1)
  1257. {
  1258. int i;
  1259. for (i = 0; i < numPrivateIPs; i++)
  1260. {
  1261. addListeningSocket(privateIPList[i]);
  1262. free(privateIPList[i]);
  1263. }
  1264. free(privateIPList);
  1265. }
  1266. # endif // HAVE_GETIFADDR
  1267. // if -L hasn't been specified on the command line, use default sockets (all IP addresses)
  1268. // maxsocket results from first pass parsing the arguments
  1269. if (!maxsockets)
  1270. {
  1271. # if HAVE_GETIFADDR
  1272. if (!(PublicIPProtectionLevel & 1) && haveIPv6Stack) addListeningSocket("::");
  1273. if (!(PublicIPProtectionLevel & 1) && haveIPv4Stack) addListeningSocket("0.0.0.0");
  1274. # else // !HAVE_GETIFADDR
  1275. if (haveIPv6Stack) addListeningSocket("::");
  1276. if (haveIPv4Stack) addListeningSocket("0.0.0.0");
  1277. # endif // !HAVE_GETIFADDR
  1278. }
  1279. if (!numsockets)
  1280. {
  1281. printerrorf("Fatal: Could not listen on any socket.\n");
  1282. return(!0);
  1283. }
  1284. return 0;
  1285. }
  1286. #endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
  1287. int server_main(int argc, CARGV argv)
  1288. {
  1289. // Initialize ePID / HwId parameters
  1290. memset(KmsResponseParameters, 0, sizeof(KmsResponseParameters));
  1291. global_argc = argc;
  1292. global_argv = argv;
  1293. # ifdef _NTSERVICE
  1294. DWORD lasterror = ERROR_SUCCESS;
  1295. if (!StartServiceCtrlDispatcher(NTServiceDispatchTable) && (lasterror = GetLastError()) == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
  1296. {
  1297. IsNTService = FALSE;
  1298. return newmain();
  1299. }
  1300. return lasterror;
  1301. # else // !_NTSERVICE
  1302. return newmain();
  1303. # endif // !_NTSERVICE
  1304. }
  1305. int newmain()
  1306. {
  1307. // Initialize thread synchronization objects for Windows and Cygwin
  1308. # ifdef USE_THREADS
  1309. # ifndef NO_LOG
  1310. // Initialize the Critical Section for proper logging
  1311. # if _WIN32
  1312. InitializeCriticalSection(&logmutex);
  1313. # endif // _WIN32
  1314. # endif // NO_LOG
  1315. # endif // USE_THREADS
  1316. # ifdef _WIN32
  1317. # ifndef USE_MSRPC
  1318. WSADATA wsadata;
  1319. {
  1320. // Windows Sockets must be initialized
  1321. int error;
  1322. if ((error = WSAStartup(0x0202, &wsadata)))
  1323. {
  1324. printerrorf("Fatal: Could not initialize Windows sockets (Error: %d).\n", error);
  1325. return error;
  1326. }
  1327. }
  1328. # endif // USE_MSRPC
  1329. // Windows can never daemonize
  1330. //nodaemon = 1;
  1331. # else // __CYGWIN__
  1332. // Do not daemonize if we are a Windows service
  1333. # ifdef _NTSERVICE
  1334. if (IsNTService) nodaemon = 1;
  1335. # endif
  1336. # endif // _WIN32 / __CYGWIN__
  1337. parseGeneralArguments(); // Does not return if an error occurs
  1338. # if !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
  1339. struct stat statbuf;
  1340. fstat(STDIN_FILENO, &statbuf);
  1341. if (S_ISSOCK(statbuf.st_mode))
  1342. {
  1343. InetdMode = 1;
  1344. nodaemon = 1;
  1345. # ifndef SIMPLE_SOCKETS
  1346. maxsockets = 0;
  1347. # endif // SIMPLE_SOCKETS
  1348. # ifndef NO_LOG
  1349. logstdout = 0;
  1350. # endif // NO_LOG
  1351. }
  1352. # endif // !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
  1353. # ifndef NO_INI_FILE
  1354. if (fn_ini && !readIniFile(INI_FILE_PASS_1))
  1355. {
  1356. # ifdef INI_FILE
  1357. if (strcmp(fn_ini, INI_FILE))
  1358. # endif // INI_FILE
  1359. printerrorf("Warning: Can't read %s: %s\n", fn_ini, strerror(errno));
  1360. }
  1361. # endif // NO_INI_FILE
  1362. # if defined(USE_MSRPC) && !defined(NO_PRIVATE_IP_DETECT)
  1363. if (PublicIPProtectionLevel)
  1364. {
  1365. printerrorf("Warning: Public IP address protection using MS RPC is poor. See vlmcsd.8\n");
  1366. }
  1367. # endif // defined(USE_MSRPC) && !defined(NO_PRIVATE_IP_DETECT)
  1368. # if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__ && !defined(USE_MSRPC)
  1369. allocateSemaphore();
  1370. # endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && __minix__
  1371. # ifdef _NTSERVICE
  1372. if (installService)
  1373. return NtServiceInstallation(installService, ServiceUser, ServicePassword);
  1374. # endif // _NTSERVICE
  1375. # if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
  1376. if (!InetdMode)
  1377. {
  1378. int error;
  1379. # ifdef SIMPLE_SOCKETS
  1380. if ((error = listenOnAllAddresses())) return error;
  1381. # else // !SIMPLE_SOCKETS
  1382. if ((error = setupListeningSockets())) return error;
  1383. # endif // !SIMPLE_SOCKETS
  1384. }
  1385. # endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
  1386. // After sockets have been set up, we may switch to a lower privileged user
  1387. # if !defined(_WIN32) && !defined(NO_USER_SWITCH)
  1388. # ifndef NO_SIGHUP
  1389. if (!IsRestarted)
  1390. {
  1391. # endif // NO_SIGHUP
  1392. if (gid != INVALID_GID)
  1393. {
  1394. if (setgid(gid))
  1395. {
  1396. printerrorf("Fatal: %s for %s failed: %s\n", "setgid", gname, strerror(errno));
  1397. return errno;
  1398. }
  1399. if (setgroups(1, &gid))
  1400. {
  1401. printerrorf("Fatal: %s for %s failed: %s\n", "setgroups", gname, strerror(errno));
  1402. return errno;
  1403. }
  1404. }
  1405. if (uid != INVALID_UID && setuid(uid))
  1406. {
  1407. printerrorf("Fatal: %s for %s failed: %s\n", "setuid", uname, strerror(errno));
  1408. return errno;
  1409. }
  1410. # ifndef NO_SIGHUP
  1411. }
  1412. # endif // NO_SIGHUP
  1413. # endif // !defined(_WIN32) && !defined(NO_USER_SWITCH)
  1414. randomNumberInit();
  1415. // Randomization Level 1 means generate ePIDs at startup and use them during
  1416. // the lifetime of the process. So we generate them now
  1417. # ifndef NO_RANDOM_EPID
  1418. if (RandomizationLevel == 1) randomPidInit();
  1419. # endif
  1420. # if !defined(NO_SOCKETS)
  1421. # ifdef _WIN32
  1422. if (!IsNTService)
  1423. {
  1424. # endif // _WIN32
  1425. int error;
  1426. if ((error = daemonizeAndSetSignalAction())) return error;
  1427. # ifdef _WIN32
  1428. }
  1429. # endif // _WIN32
  1430. # endif // !defined(NO_SOCKETS)
  1431. writePidFile();
  1432. # if !defined(NO_LOG) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
  1433. if (!InetdMode)
  1434. logger("vlmcsd %s started successfully\n", Version);
  1435. # endif // !defined(NO_LOG) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
  1436. # if defined(_NTSERVICE) && !defined(USE_MSRPC)
  1437. if (IsNTService) ReportServiceStatus(SERVICE_RUNNING, NO_ERROR, 200);
  1438. # endif // defined(_NTSERVICE) && !defined(USE_MSRPC)
  1439. int rc;
  1440. rc = runServer();
  1441. // Clean up things and exit
  1442. # ifdef _NTSERVICE
  1443. if (!ServiceShutdown)
  1444. # endif
  1445. cleanup();
  1446. # ifdef _NTSERVICE
  1447. else
  1448. ReportServiceStatus(SERVICE_STOPPED, NO_ERROR, 0);
  1449. # endif
  1450. return rc;
  1451. }