| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832 |
- #ifndef CONFIG
- #define CONFIG "config.h"
- #endif // CONFIG
- #include CONFIG
- #if defined(USE_MSRPC) && !defined(_WIN32) && !defined(__CYGWIN__)
- #error Microsoft RPC is only available on Windows and Cygwin
- #endif
- #if defined(USE_MSRPC) && defined(SIMPLE_SOCKETS)
- #error You can only define either USE_MSRPC or SIMPLE_SOCKETS but not both
- #endif
- #if defined(NO_SOCKETS) && defined(USE_MSRPC)
- #error Cannot use inetd mode with Microsoft RPC
- #endif
- #ifndef _GNU_SOURCE
- #define _GNU_SOURCE
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <stdint.h>
- #ifndef _WIN32
- #include <pwd.h>
- #include <grp.h>
- #include <sys/types.h>
- #if !defined(NO_LIMIT) && !__minix__
- #include <sys/ipc.h>
- #if !__ANDROID__
- #include <sys/shm.h>
- #else // __ANDROID__
- #include <sys/syscall.h>
- #endif // __ANDROID__
- #endif // !defined(NO_LIMIT) && !__minix__
- #include <sys/wait.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #ifndef NO_LIMIT
- #include <semaphore.h>
- #endif // NO_LIMIT
- #endif // !_WIN32
- #if __APPLE__
- #include <mach-o/dyld.h>
- #endif // __APPLE__
- #if __linux__ && defined(USE_AUXV)
- #include <sys/auxv.h>
- #endif
- #if __FreeBSD__
- #include <sys/sysctl.h>
- #endif
- #include "vlmcsd.h"
- #include "endian.h"
- #include "shared_globals.h"
- #include "output.h"
- #ifndef USE_MSRPC
- #include "network.h"
- #else // USE_MSRPC
- #include "msrpc-server.h"
- #endif // USE_MSRPC
- #include "ntservice.h"
- #include "helpers.h"
- 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";
- #if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
- static uint_fast8_t maxsockets = 0;
- #endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
- #ifdef _NTSERVICE
- static int_fast8_t installService = 0;
- static const char *restrict ServiceUser = NULL;
- static const char *restrict ServicePassword = "";
- #endif
- #ifndef NO_PID_FILE
- static const char *fn_pid = NULL;
- #endif
- #ifndef NO_INI_FILE
- #ifdef INI_FILE
- static const char *fn_ini = INI_FILE;
- #else // !INI_FILE
- static const char *fn_ini = NULL;
- #endif // !INI_FILE
- static const char* IniFileErrorMessage = "";
- char* IniFileErrorBuffer = NULL;
- #define INIFILE_ERROR_BUFFERSIZE 256
- static IniFileParameter_t IniFileParameterList[] =
- {
- # ifndef NO_BASIC_PRODUCT_LIST
- { "Windows", INI_PARAM_WINDOWS },
- { "Office2010", INI_PARAM_OFFICE2010 },
- { "Office2013", INI_PARAM_OFFICE2013 },
- { "Office2016", INI_PARAM_OFFICE2016 },
- # endif // NO_BASIC_PRODUCT_LIST
- # ifndef NO_RANDOM_EPID
- { "RandomizationLevel", INI_PARAM_RANDOMIZATION_LEVEL },
- { "LCID", INI_PARAM_LCID },
- # endif // NO_RANDOM_EPID
- # if !defined(NO_SOCKETS) && (defined(USE_MSRPC) || defined(SIMPLE_SOCKETS) || defined(HAVE_GETIFADDR))
- { "Port", INI_PARAM_PORT },
- # endif // defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)
- # if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- # ifndef SIMPLE_SOCKETS
- { "Listen", INI_PARAM_LISTEN },
- # endif // SIMPLE_SOCKETS
- # if HAVE_FREEBIND
- { "FreeBind", INI_PARAM_FREEBIND },
- # endif // HAVE_FREEBIND
- # if !defined(NO_LIMIT) && !__minix__
- { "MaxWorkers", INI_PARAM_MAX_WORKERS },
- # endif // !defined(NO_LIMIT) && !__minix__
- # endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- # if !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC) & !defined(USE_MSRPC)
- { "ConnectionTimeout", INI_PARAM_CONNECTION_TIMEOUT },
- # endif // !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC) & !defined(USE_MSRPC)
- # ifndef USE_MSRPC
- { "DisconnectClientsImmediately", INI_PARAM_DISCONNECT_IMMEDIATELY },
- { "UseNDR64", INI_PARAM_RPC_NDR64 },
- { "UseBTFN", INI_PARAM_RPC_BTFN },
- # endif // USE_MSRPC
- # ifndef NO_PID_FILE
- { "PIDFile", INI_PARAM_PID_FILE },
- # endif // NO_PID_FILE
- # ifndef NO_LOG
- { "LogDateAndTime", INI_PARAM_LOG_DATE_AND_TIME },
- { "LogFile", INI_PARAM_LOG_FILE },
- # ifndef NO_VERBOSE_LOG
- { "LogVerbose", INI_PARAM_LOG_VERBOSE },
- # endif // NO_VERBOSE_LOG
- # endif // NO_LOG
- # ifndef NO_CUSTOM_INTERVALS
- {"ActivationInterval", INI_PARAM_ACTIVATION_INTERVAL },
- {"RenewalInterval", INI_PARAM_RENEWAL_INTERVAL },
- # endif // NO_CUSTOM_INTERVALS
- # if !defined(NO_USER_SWITCH) && !defined(_WIN32)
- { "user", INI_PARAM_UID },
- { "group", INI_PARAM_GID},
- # endif // !defined(NO_USER_SWITCH) && !defined(_WIN32)
- # if !defined(NO_PRIVATE_IP_DETECT)
- {"PublicIPProtectionLevel", INI_PARAM_PUBLIC_IP_PROTECTION_LEVEL },
- # endif
- };
- #endif // NO_INI_FILE
- #if !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
- #if !defined(USE_THREADS) && !defined(CYGWIN) && !defined(USE_MSRPC)
- static int shmid = -1;
- #endif
- #if __ANDROID__ && !defined(USE_THREADS) // Bionic does not wrap these syscalls (willingly because Google fears, developers don't know how to use it)
- #ifdef __NR_shmget
- static int shmget(key_t key, size_t size, int shmflg)
- {
- return syscall(__NR_shmget, key, size, shmflg);
- }
- #endif // __NR_shmget
- #ifdef __NR_shmat
- static void *shmat(int shmid, const void *shmaddr, int shmflg)
- {
- return (void *)syscall(__NR_shmat, shmid, shmaddr, shmflg);
- }
- #endif // __NR_shmat
- #ifdef __NR_shmdt
- static int shmdt(const void *shmaddr)
- {
- return syscall(__NR_shmdt, shmaddr);
- }
- #endif // __NR_shmdt
- #ifdef __NR_shmctl
- static int shmctl(int shmid, int cmd, /*struct shmid_ds*/void *buf)
- {
- return syscall(__NR_shmctl, shmid, cmd, buf);
- }
- #endif // __NR_shmctl
- #endif // __ANDROID__ && !defined(USE_THREADS)
- #endif // !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
- #ifndef NO_USER_SWITCH
- #ifndef _WIN32
- static const char *uname = NULL, *gname = NULL;
- static gid_t gid = INVALID_GID;
- static uid_t uid = INVALID_UID;
- // Get Numeric id of user/group
- static char GetNumericId(gid_t *restrict id, const char *const c)
- {
- char* endptr;
- gid_t temp;
- temp = (gid_t)strtoll(c, &endptr, 10);
- if (!*endptr) *id = temp;
- if (*endptr || temp == (gid_t)-1) errno = EINVAL;
- return *endptr || *id == (gid_t)-1;
- }
- // Get group id from option argument
- static char GetGid()
- {
- struct group *g;
- if ((g = getgrnam(optarg)))
- gid = g->gr_gid;
- else
- return GetNumericId(&gid, optarg);
- return 0;
- }
- // Get user id from option argument
- static char GetUid()
- {
- struct passwd *u;
- ////PORTABILITY: Assumes uid_t and gid_t are of same size (shouldn't be a problem)
- if ((u = getpwnam(optarg)))
- uid = u->pw_uid;
- else
- return GetNumericId((gid_t*)&uid, optarg);
- return 0;
- }
- #endif // _WIN32
- #endif //NO_USER_SWITCH
- #ifdef NO_HELP
- static __noreturn void usage()
- {
- printerrorf("Incorrect parameters\n\n");
- exit(!0);
- }
- #else // HELP
- static __noreturn void usage()
- {
- printerrorf("vlmcsd %s\n"
- "\nUsage:\n"
- " %s [ options ]\n\n"
- "Where:\n"
- #ifndef NO_CL_PIDS
- #ifndef NO_BASIC_PRODUCT_LIST
- " -w <ePID> always use <ePID> for Windows\n"
- " -0 <ePID> always use <ePID> for Office2010\n"
- " -3 <ePID> always use <ePID> for Office2013\n"
- " -6 <ePID> always use <ePID> for Office2016\n"
- #endif // NO_BASIC_PRODUCT_LIST
- " -H <HwId> always use hardware Id <HwId>\n"
- #endif // NO_CL_PIDS
- #if !defined(_WIN32) && !defined(NO_USER_SWITCH)
- " -u <user> set uid to <user>\n"
- " -g <group> set gid to <group>\n"
- #endif // !defined(_WIN32) && !defined(NO_USER_SWITCH)
- #ifndef NO_RANDOM_EPID
- " -r 0|1|2\t\tset ePID randomization level (default 1)\n"
- " -C <LCID>\t\tuse fixed <LCID> in random ePIDs\n"
- #endif // NO_RANDOM_EPID
- #if !defined(NO_PRIVATE_IP_DETECT)
- #if HAVE_GETIFADDR
- " -o 0|1|2|3\t\tset protection level against clients with public IP addresses (default 0)\n"
- #else // !HAVE_GETIFADDR
- #ifndef USE_MSRPC
- " -o 0|2\t\tset protection level against clients with public IP addresses (default 0)\n"
- #else // USE_MSRPC
- " -o 0|2\t\tset protection level against clients with public IP addresses (default 0). Limited use with MS RPC\n"
- #endif // USE_MSRPC
- #endif // !HAVE_GETIFADDR
- #endif // !defined(NO_PRIVATE_IP_DETECT)
- #ifndef NO_SOCKETS
- #if !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
- " -L <address>[:<port>]\tlisten on IP address <address> with optional <port>\n"
- " -P <port>\t\tset TCP port <port> for subsequent -L statements (default 1688)\n"
- #if HAVE_FREEBIND
- " -F0, -F1\t\tdisable/enable binding to foreign IP addresses\n"
- #endif // HAVE_FREEBIND
- #else // defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)
- " -P <port>\t\tuse TCP port <port> (default 1688)\n"
- #endif // defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)
- #if !defined(NO_LIMIT) && !__minix__
- " -m <clients>\t\tHandle max. <clients> simultaneously (default no limit)\n"
- #endif // !defined(NO_LIMIT) && !__minix__
- #ifdef _NTSERVICE
- " -s install vlmcsd as an NT service. Ignores -e"
- #ifndef _WIN32
- ", -f and -D"
- #endif // _WIN32
- "\n"
- " -S remove vlmcsd service. Ignores all other options\n"
- " -U <username> run NT service as <username>. Must be used with -s\n"
- " -W <password> optional <password> for -U. Must be used with -s\n"
- #endif // _NTSERVICE
- #ifndef NO_LOG
- " -e log to stdout\n"
- #endif // NO_LOG
- #ifndef _WIN32 //
- " -D run in foreground\n"
- #else // _WIN32
- " -D does nothing. Provided for compatibility with POSIX versions only\n"
- #endif // _WIN32
- #endif // NO_SOCKETS
- #ifndef USE_MSRPC
- #if !defined(NO_TIMEOUT) && !__minix__
- " -t <seconds>\t\tdisconnect clients after <seconds> of inactivity (default 30)\n"
- #endif // !defined(NO_TIMEOUT) && !__minix__
- " -d\t\t\tdisconnect clients after each request\n"
- " -k\t\t\tdon't disconnect clients after each request (default)\n"
- " -N0, -N1\t\tdisable/enable NDR64\n"
- " -B0, -B1\t\tdisable/enable bind time feature negotiation\n"
- #endif // USE_MSRPC
- #ifndef NO_PID_FILE
- " -p <file> write pid to <file>\n"
- #endif // NO_PID_FILE
- #ifndef NO_INI_FILE
- " -i <file>\t\tuse config file <file>\n"
- #endif // NO_INI_FILE
- #ifndef NO_CUSTOM_INTERVALS
- " -R <interval> renew activation every <interval> (default 1w)\n"
- " -A <interval> retry activation every <interval> (default 2h)\n"
- #endif // NO_CUSTOM_INTERVALS
- #ifndef NO_LOG
- #ifndef _WIN32
- " -l syslog log to syslog\n"
- #endif // _WIN32
- " -l <file> log to <file>\n"
- " -T0, -T1\t\tdisable/enable logging with time and date (default -T1)\n"
- #ifndef NO_VERBOSE_LOG
- " -v\t\t\tlog verbose\n"
- " -q\t\t\tdon't log verbose (default)\n"
- #endif // NO_VERBOSE_LOG
- #endif // NO_LOG
- #ifndef NO_VERSION_INFORMATION
- " -V display version information and exit\n"
- #endif // NO_VERSION_INFORMATION
- ,
- Version, global_argv[0]);
- exit(!0);
- }
- #endif // HELP
- #ifndef NO_CUSTOM_INTERVALS
- // Convert time span strings (e.g. "2h", "5w") to minutes
- __pure static DWORD timeSpanString2Minutes(const char *const restrict argument)
- {
- char *unitId;
- long long val = strtoll(argument, &unitId, 10);
- switch(toupper((int)*unitId))
- {
- case 0:
- case 'M':
- break;
- case 'H':
- val *= 60;
- break;
- case 'D':
- val *= 60 * 24;
- break;
- case 'W':
- val *= 60 * 24 * 7;
- break;
- case 'S':
- val /= 60;
- break;
- default:
- return 0;
- }
- if (val < 1) val = 1;
- if (val > UINT_MAX) val = UINT_MAX;
- return (DWORD)val;
- }
- #ifndef NO_INI_FILE
- __pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char *const restrict argument)
- {
- DWORD val = timeSpanString2Minutes(argument);
- if (!val)
- {
- IniFileErrorMessage = "Incorrect time span.";
- return FALSE;
- }
- *result = val;
- return TRUE;
- }
- #endif // NO_INI_FILE
- __pure static DWORD getTimeSpanFromCommandLine(const char *const restrict optarg, const char optchar)
- {
- long long val = timeSpanString2Minutes(optarg);
- if (!val)
- {
- printerrorf("Fatal: No valid time span specified in option -%c.\n", optchar);
- exit (!0);
- }
- return (DWORD)val;
- }
- #endif // NO_CUSTOM_INTERVALS
- #ifndef NO_INI_FILE
- static void ignoreIniFileParameter(uint_fast8_t iniFileParameterId)
- {
- uint_fast8_t i;
- for (i = 0; i < _countof(IniFileParameterList); i++)
- {
- if (IniFileParameterList[i].Id != iniFileParameterId) continue;
- IniFileParameterList[i].Id = 0;
- break;
- }
- }
- #else // NO_INI_FILE
- #define ignoreIniFileParameter(x)
- #endif // NO_INI_FILE
- #ifndef NO_INI_FILE
- static BOOL getIniFileArgumentBool(int_fast8_t *result, const char *const argument)
- {
- IniFileErrorMessage = "Argument must be true/on/yes/1 or false/off/no/0";
- return getArgumentBool(result, argument);
- }
- static BOOL getIniFileArgumentInt(unsigned int *result, const char *const argument, const unsigned int min, const unsigned int max)
- {
- unsigned int tempResult;
- if (!stringToInt(argument, min, max, &tempResult))
- {
- snprintf(IniFileErrorBuffer, INIFILE_ERROR_BUFFERSIZE, "Must be integer between %u and %u", min, max);
- IniFileErrorMessage = IniFileErrorBuffer;
- return FALSE;
- }
- *result = tempResult;
- return TRUE;
- }
- static char* allocateStringArgument(const char *const argument)
- {
- char* result = (char*)vlmcsd_malloc(strlen(argument) + 1);
- strcpy(result, argument);
- return result;
- }
- static __pure int isControlCharOrSlash(const char c)
- {
- if ((unsigned char)c < '!') return !0;
- if (c == '/') return !0;
- return 0;
- }
- static void iniFileLineNextWord(const char **s)
- {
- while ( **s && isspace((int)**s) ) (*s)++;
- }
- static BOOL setHwIdFromIniFileLine(const char **s, const ProdListIndex_t index)
- {
- iniFileLineNextWord(s);
- if (**s == '/')
- {
- if (KmsResponseParameters[index].HwId) return TRUE;
- BYTE* HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6 *)0)->HwId));
- hex2bin(HwId, *s + 1, sizeof(((RESPONSE_V6 *)0)->HwId));
- KmsResponseParameters[index].HwId = HwId;
- }
- return TRUE;
- }
- //static BOOL checkGuidInIniFileLine(const char **s, ProdListIndex_t *const index)
- //{
- // GUID AppGuid;
- //
- // if (!string2Uuid(*s, &AppGuid)) return FALSE;
- //
- // (*s) += GUID_STRING_LENGTH;
- // getProductNameHE(&AppGuid, AppList, index);
- //
- // if (*index > getAppListSize() - 2)
- // {
- // IniFileErrorMessage = "Unknown App Guid.";
- // return FALSE;
- // }
- //
- // iniFileLineNextWord(s);
- // if ( *(*s)++ != '=' ) return FALSE;
- //
- // return TRUE;
- //}
- static BOOL setEpidFromIniFileLine(const char **s, const ProdListIndex_t index)
- {
- iniFileLineNextWord(s);
- const char *savedPosition = *s;
- uint_fast16_t i;
- for (i = 0; !isControlCharOrSlash(**s); i++)
- {
- if (utf8_to_ucs2_char((const unsigned char*)*s, (const unsigned char**)s) == (WCHAR)~0)
- {
- return FALSE;
- }
- }
- if (i < 1 || i >= PID_BUFFER_SIZE) return FALSE;
- if (KmsResponseParameters[index].Epid) return TRUE;
- size_t size = *s - savedPosition + 1;
- char* epidbuffer = (char*)vlmcsd_malloc(size);
- memcpy(epidbuffer, savedPosition, size - 1);
- epidbuffer[size - 1] = 0;
- KmsResponseParameters[index].Epid = epidbuffer;
- #ifndef NO_LOG
- KmsResponseParameters[index].EpidSource = fn_ini;
- #endif //NO_LOG
- return TRUE;
- }
- static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
- {
- unsigned int result;
- BOOL success = TRUE;
- const char *s = (const char*)iniarg;
- switch(id)
- {
- # ifndef NO_BASIC_PRODUCT_LIST
- case INI_PARAM_WINDOWS:
- setEpidFromIniFileLine(&s, 0);
- setHwIdFromIniFileLine(&s, 0);
- break;
- case INI_PARAM_OFFICE2010:
- setEpidFromIniFileLine(&s, 1);
- setHwIdFromIniFileLine(&s, 1);
- break;
- case INI_PARAM_OFFICE2013:
- setEpidFromIniFileLine(&s, 2);
- setHwIdFromIniFileLine(&s, 2);
- break;
- case INI_PARAM_OFFICE2016:
- setEpidFromIniFileLine(&s, 3);
- setHwIdFromIniFileLine(&s, 3);
- break;
- # endif
- # if !defined(NO_USER_SWITCH) && !defined(_WIN32)
- case INI_PARAM_GID:
- {
- struct group *g;
- IniFileErrorMessage = "Invalid group id or name";
- if (!(gname = allocateStringArgument(iniarg))) return FALSE;
- if ((g = getgrnam(iniarg)))
- gid = g->gr_gid;
- else
- success = !GetNumericId(&gid, iniarg);
- break;
- }
- case INI_PARAM_UID:
- {
- struct passwd *p;
- IniFileErrorMessage = "Invalid user id or name";
- if (!(uname = allocateStringArgument(iniarg))) return FALSE;
- if ((p = getpwnam(iniarg)))
- uid = p->pw_uid;
- else
- success = !GetNumericId(&uid, iniarg);
- break;
- }
- # endif // !defined(NO_USER_SWITCH) && !defined(_WIN32)
- # ifndef NO_RANDOM_EPID
- case INI_PARAM_LCID:
- success = getIniFileArgumentInt(&result, iniarg, 0, 32767);
- if (success) Lcid = (uint16_t)result;
- break;
- case INI_PARAM_RANDOMIZATION_LEVEL:
- success = getIniFileArgumentInt(&result, iniarg, 0, 2);
- if (success) RandomizationLevel = (int_fast8_t)result;
- break;
- # endif // NO_RANDOM_EPID
- # if (defined(USE_MSRPC) || defined(SIMPLE_SOCKETS) || defined(HAVE_GETIFADDR)) && !defined(NO_SOCKETS)
- case INI_PARAM_PORT:
- defaultport = allocateStringArgument(iniarg);
- break;
- # endif // (defined(USE_MSRPC) || defined(SIMPLE_SOCKETS) || defined(HAVE_GETIFADDR)) && !defined(NO_SOCKETS)
- # if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
- case INI_PARAM_LISTEN:
- maxsockets++;
- return TRUE;
- # endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
- # if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
- case INI_PARAM_MAX_WORKERS:
- # ifdef USE_MSRPC
- success = getIniFileArgumentInt(&MaxTasks, iniarg, 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT);
- # else // !USE_MSRPC
- success = getIniFileArgumentInt(&MaxTasks, iniarg, 1, SEM_VALUE_MAX);
- # endif // !USE_MSRPC
- break;
- # endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
- # ifndef NO_PID_FILE
- case INI_PARAM_PID_FILE:
- fn_pid = allocateStringArgument(iniarg);
- break;
- # endif // NO_PID_FILE
- # ifndef NO_LOG
- case INI_PARAM_LOG_FILE:
- fn_log = allocateStringArgument(iniarg);
- break;
- case INI_PARAM_LOG_DATE_AND_TIME:
- success = getIniFileArgumentBool(&LogDateAndTime, iniarg);
- break;
- # ifndef NO_VERBOSE_LOG
- case INI_PARAM_LOG_VERBOSE:
- success = getIniFileArgumentBool(&logverbose, iniarg);
- break;
- # endif // NO_VERBOSE_LOG
- # endif // NO_LOG
- # ifndef NO_CUSTOM_INTERVALS
- case INI_PARAM_ACTIVATION_INTERVAL:
- success = getTimeSpanFromIniFile(&VLActivationInterval, iniarg);
- break;
- case INI_PARAM_RENEWAL_INTERVAL:
- success = getTimeSpanFromIniFile(&VLRenewalInterval, iniarg);
- break;
- # endif // NO_CUSTOM_INTERVALS
- # ifndef USE_MSRPC
- # if !defined(NO_TIMEOUT) && !__minix__
- case INI_PARAM_CONNECTION_TIMEOUT:
- success = getIniFileArgumentInt(&result, iniarg, 1, 600);
- if (success) ServerTimeout = (DWORD)result;
- break;
- # endif // !defined(NO_TIMEOUT) && !__minix__
- case INI_PARAM_DISCONNECT_IMMEDIATELY:
- success = getIniFileArgumentBool(&DisconnectImmediately, iniarg);
- break;
- case INI_PARAM_RPC_NDR64:
- success = getIniFileArgumentBool(&UseRpcNDR64, iniarg);
- break;
- case INI_PARAM_RPC_BTFN:
- success = getIniFileArgumentBool(&UseRpcBTFN, iniarg);
- break;
- # endif // USE_MSRPC
- # if HAVE_FREEBIND
- case INI_PARAM_FREEBIND:
- success = getIniFileArgumentBool(&freebind, iniarg);
- break;
- # endif // HAVE_FREEBIND
- # if !defined(NO_PRIVATE_IP_DETECT)
- case INI_PARAM_PUBLIC_IP_PROTECTION_LEVEL:
- success = getIniFileArgumentInt(&PublicIPProtectionLevel, iniarg, 0, 3);
- # if !HAVE_GETIFADDR
- if (PublicIPProtectionLevel & 1)
- {
- IniFileErrorMessage = "Must be 0 or 2";
- success = FALSE;
- }
- # endif // !HAVE_GETIFADDR
- break;
- # endif // !defined(NO_PRIVATE_IP_DETECT)
- default:
- return FALSE;
- }
- return success;
- }
- static BOOL getIniFileArgument(const char **s)
- {
- while (!isspace((int)**s) && **s != '=' && **s) (*s)++;
- iniFileLineNextWord(s);
- if (*((*s)++) != '=')
- {
- IniFileErrorMessage = "'=' required after keyword.";
- return FALSE;
- }
- iniFileLineNextWord(s);
- if (!**s)
- {
- IniFileErrorMessage = "missing argument after '='.";
- return FALSE;
- }
- return TRUE;
- }
- static BOOL handleIniFileParameter(const char *s)
- {
- uint_fast8_t i;
- for (i = 0; i < _countof(IniFileParameterList); i++)
- {
- if (strncasecmp(IniFileParameterList[i].Name, s, strlen(IniFileParameterList[i].Name))) continue;
- if (!IniFileParameterList[i].Id) return TRUE;
- if (!getIniFileArgument(&s)) return FALSE;
- return setIniFileParameter(IniFileParameterList[i].Id, s);
- }
- IniFileErrorMessage = "Unknown keyword.";
- return FALSE;
- }
- #if !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
- static BOOL setupListeningSocketsFromIniFile(const char *s)
- {
- if (!maxsockets) return TRUE;
- if (strncasecmp("Listen", s, 6)) return TRUE;
- if (!getIniFileArgument(&s)) return TRUE;
- snprintf(IniFileErrorBuffer, INIFILE_ERROR_BUFFERSIZE, "Cannot listen on %s.", s);
- IniFileErrorMessage = IniFileErrorBuffer;
- return addListeningSocket(s);
- }
- #endif // !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
- static BOOL readIniFile(const uint_fast8_t pass)
- {
- char line[256];
- const char *s;
- unsigned int lineNumber;
- uint_fast8_t lineParseError;
- FILE *restrict f;
- BOOL result = TRUE;
- IniFileErrorBuffer = (char*)vlmcsd_malloc(INIFILE_ERROR_BUFFERSIZE);
- if ( !(f = fopen(fn_ini, "r") )) return FALSE;
- for (lineNumber = 1; (s = fgets(line, sizeof(line), f)); lineNumber++)
- {
- line[strlen(line) - 1] = 0;
- iniFileLineNextWord(&s);
- if (*s == ';' || *s == '#' || !*s) continue;
- # ifndef NO_SOCKETS
- if (pass == INI_FILE_PASS_1)
- # endif // NO_SOCKETS
- {
- if (handleIniFileParameter(s)) continue;
- lineParseError = TRUE;/*!checkGuidInIniFileLine(&s, &appIndex) ||
- !setEpidFromIniFileLine(&s, appIndex) ||
- !setHwIdFromIniFileLine(&s, appIndex);*/
- }
- # if !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
- else if (pass == INI_FILE_PASS_2)
- {
- lineParseError = !setupListeningSocketsFromIniFile(s);
- }
- else
- {
- return FALSE;
- }
- # endif // !defined(NO_SOCKETS) && && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
- if (lineParseError)
- {
- printerrorf("Warning: %s line %u: \"%s\". %s\n", fn_ini, lineNumber, line, IniFileErrorMessage);
- continue;
- }
- }
- if (ferror(f)) result = FALSE;
- free(IniFileErrorBuffer);
- fclose(f);
- # if !defined(NO_SOCKETS) && !defined(NO_LOG)
- if (pass == INI_FILE_PASS_1 && !InetdMode && result)
- {
- # ifdef _NTSERVICE
- if (!installService)
- # endif // _NTSERVICE
- logger("Read ini file %s\n", fn_ini);
- }
- # endif // !defined(NO_SOCKETS) && !defined(NO_LOG)
- return result;
- }
- #endif // NO_INI_FILE
- #if !defined(NO_SOCKETS)
- #if !defined(_WIN32)
- #if !defined(NO_SIGHUP)
- static void exec_self(char** argv)
- {
- # if __linux__ && defined(USE_AUXV)
- char *execname_ptr = (char*)getauxval(AT_EXECFN);
- if (execname_ptr) execv(execname_ptr, argv);
- # elif (__linux__ || __CYGWIN__) && !defined(NO_PROCFS)
- execv(realpath("/proc/self/exe", NULL), argv);
- # elif (__FreeBSD__) && !defined(NO_PROCFS)
- int mib[4];
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PATHNAME;
- mib[3] = -1;
- char path[PATH_MAX + 1];
- size_t cb = sizeof(path);
- if (!sysctl(mib, 4, path, &cb, NULL, 0)) execv(path, argv);
- # elif (__DragonFly__) && !defined(NO_PROCFS)
- execv(realpath("/proc/curproc/file", NULL), argv);
- # elif __NetBSD__ && !defined(NO_PROCFS)
- execv(realpath("/proc/curproc/exe", NULL), argv);
- # elif __sun__
- const char* exename = getexecname();
- if (exename) execv(exename, argv);
- # elif __APPLE__
- char path[PATH_MAX + 1];
- uint32_t size = sizeof(path);
- if (_NSGetExecutablePath(path, &size) == 0) execv(path, argv);
- # else
- execvp(argv[0], argv);
- # endif
- }
- static void HangupHandler(const int signal_unused)
- {
- int i;
- int_fast8_t daemonize_protection = TRUE;
- CARGV argv_in = multi_argv == NULL ? global_argv : multi_argv;
- int argc_in = multi_argc == 0 ? global_argc : multi_argc;
- const char** argv_out = (const char**)vlmcsd_malloc((argc_in + 2) * sizeof(char**));
- for (i = 0; i < argc_in; i++)
- {
- if (!strcmp(argv_in[i], "-Z")) daemonize_protection = FALSE;
- argv_out[i] = argv_in[i];
- }
- argv_out[argc_in] = argv_out[argc_in + 1] = NULL;
- if (daemonize_protection) argv_out[argc_in] = (char*) "-Z";
- exec_self((char**)argv_out);
- # ifndef NO_LOG
- logger("Fatal: Unable to restart on SIGHUP: %s\n", strerror(errno));
- # endif
- # ifndef NO_PID_FILE
- if (fn_pid) unlink(fn_pid);
- # endif // NO_PID_FILE
- exit(errno);
- }
- #endif // NO_SIGHUP
- static void terminationHandler(const int signal_unused)
- {
- cleanup();
- exit(0);
- }
- #if defined(CHILD_HANDLER) || __minix__
- static void childHandler(const int signal)
- {
- waitpid(-1, NULL, WNOHANG);
- }
- #endif // defined(CHILD_HANDLER) || __minix__
- static int daemonizeAndSetSignalAction()
- {
- struct sigaction sa;
- sigemptyset(&sa.sa_mask);
- # ifndef NO_LOG
- if ( !nodaemon) if (daemon(!0, logstdout))
- # else // NO_LOG
- if ( !nodaemon) if (daemon(!0, 0))
- # endif // NO_LOG
- {
- printerrorf("Fatal: Could not daemonize to background.\n");
- return(errno);
- }
- if (!InetdMode)
- {
- # ifndef USE_THREADS
- # if defined(CHILD_HANDLER) || __minix__
- sa.sa_handler = childHandler;
- # else // !(defined(CHILD_HANDLER) || __minix__)
- sa.sa_handler = SIG_IGN;
- # endif // !(defined(CHILD_HANDLER) || __minix__)
- sa.sa_flags = SA_NOCLDWAIT;
- if (sigaction(SIGCHLD, &sa, NULL))
- return(errno);
- # endif // !USE_THREADS
- sa.sa_handler = terminationHandler;
- sa.sa_flags = 0;
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
- # ifndef NO_SIGHUP
- sa.sa_handler = HangupHandler;
- sa.sa_flags = SA_NODEFER;
- sigaction(SIGHUP, &sa, NULL);
- # endif // NO_SIGHUP
- }
- return 0;
- }
- #else // _WIN32
- static BOOL terminationHandler(const DWORD fdwCtrlType)
- {
- // What a lame substitute for Unix signal handling
- switch(fdwCtrlType)
- {
- case CTRL_C_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- cleanup();
- exit(0);
- default:
- return FALSE;
- }
- }
- static DWORD daemonizeAndSetSignalAction()
- {
- if(!SetConsoleCtrlHandler( (PHANDLER_ROUTINE) terminationHandler, TRUE ))
- {
- #ifndef NO_LOG
- DWORD rc = GetLastError();
- logger("Warning: Could not register Windows signal handler: Error %u\n", rc);
- #endif // NO_LOG
- }
- return ERROR_SUCCESS;
- }
- #endif // _WIN32
- #endif // !defined(NO_SOCKETS)
- // Workaround for Cygwin fork bug (only affects cygwin processes that are Windows services)
- // Best is to compile for Cygwin with threads. fork() is slow and unreliable on Cygwin
- #if !defined(NO_INI_FILE) || !defined(NO_LOG) || !defined(NO_CL_PIDS)
- __pure static char* getCommandLineArg(char *const restrict optarg)
- {
- #if !defined (__CYGWIN__) || defined(USE_THREADS) || defined(NO_SOCKETS)
- return optarg;
- #else
- if (!IsNTService) return optarg;
- return allocateStringArgument(optarg);
- #endif
- }
- #endif // !defined(NO_INI_FILE) || !defined(NO_LOG) || !defined(NO_CL_PIDS)
- static void parseGeneralArguments() {
- int o;
- #ifndef NO_CL_PIDS
- BYTE* HwId;
- #endif // NO_CL_PIDS
- for (opterr = 0; ( o = getopt(global_argc, (char* const*)global_argv, optstring) ) > 0; ) switch (o)
- {
- #if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
- case 'Z':
- IsRestarted = TRUE;
- nodaemon = TRUE;
- break;
- #endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
- #ifndef NO_CL_PIDS
- #ifndef NO_BASIC_PRODUCT_LIST
- case 'w':
- KmsResponseParameters[APP_ID_WINDOWS].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[APP_ID_WINDOWS].EpidSource = "command line";
- #endif // NO_LOG
- break;
- case '0':
- KmsResponseParameters[APP_ID_OFFICE2010].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[APP_ID_OFFICE2010].EpidSource = "command line";
- #endif // NO_LOG
- break;
- case '3':
- KmsResponseParameters[APP_ID_OFFICE2013].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[APP_ID_OFFICE2013].EpidSource = "command line";
- #endif // NO_LOG
- break;
- case '6':
- KmsResponseParameters[3].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[3].EpidSource = "command line";
- #endif // NO_LOG
- break;
- #endif // NO_BASIC_PRODUCT_LIST
- case 'H':
- HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6 *)0)->HwId));
- hex2bin(HwId, optarg, sizeof(((RESPONSE_V6 *)0)->HwId));
- KmsResponseParameters[APP_ID_WINDOWS].HwId = HwId;
- KmsResponseParameters[APP_ID_OFFICE2010].HwId = HwId;
- KmsResponseParameters[APP_ID_OFFICE2013].HwId = HwId;
- KmsResponseParameters[3].HwId = HwId;
- break;
- #endif // NO_CL_PIDS
- #ifndef NO_SOCKETS
- case 'P':
- ignoreIniFileParameter(INI_PARAM_PORT);
- #if !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
- ignoreIniFileParameter(INI_PARAM_LISTEN);
- #else
- defaultport = optarg;
- #endif // !SIMPLE_SOCKETS
- break;
- #if !defined(NO_LIMIT) && !__minix__
- case 'm':
- #ifdef USE_MSRPC
- MaxTasks = getOptionArgumentInt(o, 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT);
- #else // !USE_MSRPC
- MaxTasks = getOptionArgumentInt(o, 1, SEM_VALUE_MAX);
- #endif // !USE_MSRPC
- ignoreIniFileParameter(INI_PARAM_MAX_WORKERS);
- break;
- #endif // !defined(NO_LIMIT) && !__minix__
- #endif // NO_SOCKETS
- #if !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC)
- case 't':
- ServerTimeout = getOptionArgumentInt(o, 1, 600);
- ignoreIniFileParameter(INI_PARAM_CONNECTION_TIMEOUT);
- break;
- #endif // !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC)
- #ifndef NO_PID_FILE
- case 'p':
- fn_pid = getCommandLineArg(optarg);
- ignoreIniFileParameter(INI_PARAM_PID_FILE);
- break;
- #endif
- #ifndef NO_INI_FILE
- case 'i':
- fn_ini = getCommandLineArg(optarg);
- if (!strcmp(fn_ini, "-")) fn_ini = NULL;
- break;
- #endif
- #ifndef NO_LOG
- case 'T':
- if (!getArgumentBool(&LogDateAndTime, optarg)) usage();
- ignoreIniFileParameter(INI_PARAM_LOG_DATE_AND_TIME);
- break;
- case 'l':
- fn_log = getCommandLineArg(optarg);
- ignoreIniFileParameter(INI_PARAM_LOG_FILE);
- break;
- #ifndef NO_VERBOSE_LOG
- case 'v':
- case 'q':
- logverbose = o == 'v';
- ignoreIniFileParameter(INI_PARAM_LOG_VERBOSE);
- break;
- #endif // NO_VERBOSE_LOG
- #endif // NO_LOG
- #if !defined(NO_PRIVATE_IP_DETECT)
- case 'o':
- ignoreIniFileParameter(INI_PARAM_PUBLIC_IP_PROTECTION_LEVEL);
- PublicIPProtectionLevel = getOptionArgumentInt(o, 0, 3);
- #if !HAVE_GETIFADDR
- if (PublicIPProtectionLevel & 1) usage();
- #endif // !HAVE_GETIFADDR
- break;
- #endif // !defined(NO_PRIVATE_IP_DETECT)
- #ifndef NO_SOCKETS
- #if !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
- case 'L':
- maxsockets++;
- ignoreIniFileParameter(INI_PARAM_LISTEN);
- break;
- #if HAVE_FREEBIND
- case 'F':
- if (!getArgumentBool(&freebind, optarg)) usage();
- ignoreIniFileParameter(INI_PARAM_FREEBIND);
- break;
- #endif // HAVE_FREEBIND
- #endif // !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
- #ifdef _NTSERVICE
- case 'U':
- ServiceUser = optarg;
- break;
- case 'W':
- ServicePassword = optarg;
- break;
- case 's':
- #ifndef USE_MSRPC
- if (InetdMode) usage();
- #endif // USE_MSRPC
- if (!IsNTService) installService = 1; // Install
- break;
- case 'S':
- if (!IsNTService) installService = 2; // Remove
- break;
- #endif // _NTSERVICE
- case 'D':
- #ifndef _WIN32
- nodaemon = 1;
- #else // _WIN32
- #ifdef _PEDANTIC
- printerrorf("Warning: Option -D has no effect in the Windows version of vlmcsd.\n");
- #endif // _PEDANTIC
- #endif // _WIN32
- break;
- #ifndef NO_LOG
- case 'e':
- logstdout = 1;
- break;
- #endif // NO_LOG
- #endif // NO_SOCKETS
- #ifndef NO_RANDOM_EPID
- case 'r':
- RandomizationLevel = (int_fast8_t)getOptionArgumentInt(o, 0, 2);
- ignoreIniFileParameter(INI_PARAM_RANDOMIZATION_LEVEL);
- break;
- case 'C':
- Lcid = (uint16_t)getOptionArgumentInt(o, 0, 32767);
- ignoreIniFileParameter(INI_PARAM_LCID);
- #ifdef _PEDANTIC
- if (!IsValidLcid(Lcid))
- {
- printerrorf("Warning: %s is not a valid LCID.\n", optarg);
- }
- #endif // _PEDANTIC
- break;
- #endif // NO_RANDOM_PID
- #if !defined(NO_USER_SWITCH) && !defined(_WIN32)
- case 'g':
- gname = optarg;
- ignoreIniFileParameter(INI_PARAM_GID);
- #ifndef NO_SIGHUP
- if (!IsRestarted)
- #endif // NO_SIGHUP
- if (GetGid())
- {
- printerrorf("Fatal: %s for %s failed: %s\n", "setgid", gname, strerror(errno));
- exit(errno);
- }
- break;
- case 'u':
- uname = optarg;
- ignoreIniFileParameter(INI_PARAM_UID);
- #ifndef NO_SIGHUP
- if (!IsRestarted)
- #endif // NO_SIGHUP
- if (GetUid())
- {
- printerrorf("Fatal: %s for %s failed: %s\n", "setuid", uname, strerror(errno));
- exit(errno);
- }
- break;
- #endif // NO_USER_SWITCH && !_WIN32
- #ifndef NO_CUSTOM_INTERVALS
- case 'R':
- VLRenewalInterval = getTimeSpanFromCommandLine(optarg, o);
- ignoreIniFileParameter(INI_PARAM_RENEWAL_INTERVAL);
- break;
- case 'A':
- VLActivationInterval = getTimeSpanFromCommandLine(optarg, o);
- ignoreIniFileParameter(INI_PARAM_ACTIVATION_INTERVAL);
- break;
- #endif
- #ifndef USE_MSRPC
- case 'd':
- case 'k':
- DisconnectImmediately = o == 'd';
- ignoreIniFileParameter(INI_PARAM_DISCONNECT_IMMEDIATELY);
- break;
- case 'N':
- if (!getArgumentBool(&UseRpcNDR64, optarg)) usage();
- ignoreIniFileParameter(INI_PARAM_RPC_NDR64);
- break;
- case 'B':
- if (!getArgumentBool(&UseRpcBTFN, optarg)) usage();
- ignoreIniFileParameter(INI_PARAM_RPC_BTFN);
- break;
- #endif // !USE_MSRPC
- #ifndef NO_VERSION_INFORMATION
- case 'V':
- #ifdef _NTSERVICE
- if (IsNTService) break;
- #endif
- #if defined(__s390__) && !defined(__zarch__) && !defined(__s390x__)
- printf("vlmcsd %s %i-bit\n", Version, sizeof(void*) == 4 ? 31 : (int)sizeof(void*) << 3);
- #else
- printf("vlmcsd %s %i-bit\n", Version, (int)sizeof(void*) << 3);
- #endif // defined(__s390__) && !defined(__zarch__) && !defined(__s390x__)
- printPlatform();
- printCommonFlags();
- printServerFlags();
- exit(0);
- #endif // NO_VERSION_INFORMATION
- default:
- usage();
- }
- // Do not allow non-option arguments
- if (optind != global_argc)
- usage();
- #ifdef _NTSERVICE
- // -U and -W must be used with -s
- if ((ServiceUser || *ServicePassword) && installService != 1) usage();
- #endif // _NTSERVICE
- }
- #ifndef NO_PID_FILE
- static void writePidFile()
- {
- # ifndef NO_SIGHUP
- if (IsRestarted) return;
- # endif // NO_SIGHUP
- if (fn_pid && !InetdMode)
- {
- FILE *_f = fopen(fn_pid, "w");
- if ( _f )
- {
- fprintf(_f, "%u", (uint32_t)getpid());
- fclose(_f);
- }
- #ifndef NO_LOG
- else
- {
- logger("Warning: Cannot write pid file '%s'. %s.\n", fn_pid, strerror(errno));
- }
- #endif // NO_LOG
- }
- }
- #else
- #define writePidFile(x)
- #endif // NO_PID_FILE
- #if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- void cleanup()
- {
- if (!InetdMode)
- {
- #ifndef NO_PID_FILE
- if (fn_pid) unlink(fn_pid);
- #endif // NO_PID_FILE
- closeAllListeningSockets();
- #if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !defined(_WIN32) && !__minix__
- sem_unlink("/vlmcsd");
- #if !defined(USE_THREADS) && !defined(CYGWIN)
- if (shmid >= 0)
- {
- if (Semaphore != (sem_t*)-1) shmdt(Semaphore);
- shmctl(shmid, IPC_RMID, NULL);
- }
- #endif // !defined(USE_THREADS) && !defined(CYGWIN)
- #endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !defined(_WIN32) && !__minix__
- #ifndef NO_LOG
- logger("vlmcsd %s was shutdown\n", Version);
- #endif // NO_LOG
- }
- }
- #elif defined(USE_MSRPC)
- void cleanup()
- {
- # ifndef NO_PID_FILE
- if (fn_pid) unlink(fn_pid);
- # endif // NO_PID_FILE
- # ifndef NO_LOG
- logger("vlmcsd %s was shutdown\n", Version);
- # endif // NO_LOG
- }
- #else // Neither Sockets nor RPC
- __pure void cleanup() {}
- #endif // Neither Sockets nor RPC
- #if !defined(USE_MSRPC) && !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
- // Get a semaphore for limiting the maximum concurrent tasks
- static void allocateSemaphore(void)
- {
- #ifdef USE_THREADS
- #define sharemode 0
- #else
- #define sharemode 1
- #endif
- #ifndef _WIN32
- sem_unlink("/vlmcsd");
- #endif
- if(MaxTasks < SEM_VALUE_MAX && !InetdMode)
- {
- #ifndef _WIN32
- #if !defined(USE_THREADS) && !defined(CYGWIN)
- if ((Semaphore = sem_open("/vlmcsd", O_CREAT /*| O_EXCL*/, 0700, MaxTasks)) == SEM_FAILED) // fails on many systems
- {
- // We didn't get a named Semaphore (/dev/shm on Linux) so let's try our own shared page
- if (
- ( shmid = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600) ) < 0 ||
- ( Semaphore = (sem_t*)shmat(shmid, NULL, 0) ) == (sem_t*)-1 ||
- sem_init(Semaphore, 1, MaxTasks) < 0
- )
- {
- int errno_save = errno;
- if (Semaphore != (sem_t*)-1) shmdt(Semaphore);
- if (shmid >= 0) shmctl(shmid, IPC_RMID, NULL);
- printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno_save));
- MaxTasks = SEM_VALUE_MAX;
- }
- }
- #else // THREADS or CYGWIN
- Semaphore = (sem_t*)vlmcsd_malloc(sizeof(sem_t));
- if (sem_init(Semaphore, sharemode, MaxTasks) < 0) // sem_init is not implemented on Darwin (returns ENOSYS)
- {
- free(Semaphore);
- if ((Semaphore = sem_open("/vlmcsd", O_CREAT /*| O_EXCL*/, 0700, MaxTasks)) == SEM_FAILED)
- {
- printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno));
- MaxTasks = SEM_VALUE_MAX;
- }
- }
- #endif // THREADS or CYGWIN
- #else // _WIN32
- if (!(Semaphore = CreateSemaphoreA(NULL, MaxTasks, MaxTasks, NULL)))
- {
- printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(GetLastError()));
- MaxTasks = SEM_VALUE_MAX;
- }
- #endif // _WIN32
- }
- }
- #endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
- #if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
- int setupListeningSockets()
- {
- int o;
- # if HAVE_GETIFADDR
- char** privateIPList;
- int numPrivateIPs = 0;
- if (PublicIPProtectionLevel & 1) getPrivateIPAddresses(&numPrivateIPs, &privateIPList);
- uint_fast8_t allocsockets = maxsockets ? (maxsockets + numPrivateIPs) : ((PublicIPProtectionLevel & 1) ? numPrivateIPs : 2);
- # else // !HAVE_GETIFADDR
- uint_fast8_t allocsockets = maxsockets ? maxsockets : 2;
- # endif // !HAVE_GETIFADDR
- SocketList = (SOCKET*)vlmcsd_malloc((size_t)allocsockets * sizeof(SOCKET));
- int_fast8_t haveIPv4Stack = checkProtocolStack(AF_INET);
- int_fast8_t haveIPv6Stack = checkProtocolStack(AF_INET6);
- // Reset getopt since we've alread used it
- optReset();
- for (opterr = 0; ( o = getopt(global_argc, (char* const*)global_argv, optstring) ) > 0; ) switch (o)
- {
- case 'P':
- defaultport = optarg;
- break;
- case 'L':
- addListeningSocket(optarg);
- break;
- default:
- break;
- }
- # ifndef NO_INI_FILE
- if (maxsockets && !numsockets)
- {
- if (fn_ini && !readIniFile(INI_FILE_PASS_2))
- {
- #ifdef INI_FILE
- if (strcmp(fn_ini, INI_FILE))
- #endif // INI_FILE
- printerrorf("Warning: Can't read %s: %s\n", fn_ini, strerror(errno));
- }
- }
- # endif
- # if HAVE_GETIFADDR
- if (PublicIPProtectionLevel & 1)
- {
- int i;
- for (i = 0; i < numPrivateIPs; i++)
- {
- addListeningSocket(privateIPList[i]);
- free(privateIPList[i]);
- }
- free(privateIPList);
- }
- # endif // HAVE_GETIFADDR
- // if -L hasn't been specified on the command line, use default sockets (all IP addresses)
- // maxsocket results from first pass parsing the arguments
- if (!maxsockets)
- {
- # if HAVE_GETIFADDR
- if (!(PublicIPProtectionLevel & 1) && haveIPv6Stack) addListeningSocket("::");
- if (!(PublicIPProtectionLevel & 1) && haveIPv4Stack) addListeningSocket("0.0.0.0");
- # else // !HAVE_GETIFADDR
- if (haveIPv6Stack) addListeningSocket("::");
- if (haveIPv4Stack) addListeningSocket("0.0.0.0");
- # endif // !HAVE_GETIFADDR
- }
- if (!numsockets)
- {
- printerrorf("Fatal: Could not listen on any socket.\n");
- return(!0);
- }
- return 0;
- }
- #endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
- int server_main(int argc, CARGV argv)
- {
- #if !defined(_NTSERVICE) && !defined(NO_SOCKETS)
- int error;
- #endif // !defined(_NTSERVICE) && !defined(NO_SOCKETS)
- // Initialize ePID / HwId parameters
- memset(KmsResponseParameters, 0, sizeof(KmsResponseParameters));
- global_argc = argc;
- global_argv = argv;
- #ifdef _NTSERVICE // #endif is in newmain()
- DWORD lasterror = ERROR_SUCCESS;
- if (!StartServiceCtrlDispatcher(NTServiceDispatchTable) && (lasterror = GetLastError()) == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
- {
- IsNTService = FALSE;
- return newmain();
- }
- return lasterror;
- }
- int newmain()
- {
- int error;
- // Initialize thread synchronization objects for Windows and Cygwin
- #ifdef USE_THREADS
- #ifndef NO_LOG
- // Initialize the Critical Section for proper logging
- InitializeCriticalSection(&logmutex);
- #endif // NO_LOG
- #endif // USE_THREADS
- #ifdef _WIN32
- #ifndef USE_MSRPC
- // Windows Sockets must be initialized
- WSADATA wsadata;
- if ((error = WSAStartup(0x0202, &wsadata)))
- {
- printerrorf("Fatal: Could not initialize Windows sockets (Error: %d).\n", error);
- return error;
- }
- #endif // USE_MSRPC
- // Windows can never daemonize
- //nodaemon = 1;
- #else // __CYGWIN__
- // Do not daemonize if we are a Windows service
- if (IsNTService) nodaemon = 1;
- #endif // _WIN32 / __CYGWIN__
- #endif // _NTSERVICE ( #ifdef is main(int argc, CARGV argv) )
- parseGeneralArguments(); // Does not return if an error occurs
- #if !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- struct stat statbuf;
- fstat(STDIN_FILENO, &statbuf);
- if (S_ISSOCK(statbuf.st_mode))
- {
- InetdMode = 1;
- nodaemon = 1;
- #ifndef SIMPLE_SOCKETS
- maxsockets = 0;
- #endif // SIMPLE_SOCKETS
- #ifndef NO_LOG
- logstdout = 0;
- #endif // NO_LOG
- }
- #endif // !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- #ifndef NO_INI_FILE
- if (fn_ini && !readIniFile(INI_FILE_PASS_1))
- {
- #ifdef INI_FILE
- if (strcmp(fn_ini, INI_FILE))
- #endif // INI_FILE
- printerrorf("Warning: Can't read %s: %s\n", fn_ini, strerror(errno));
- }
- #endif // NO_INI_FILE
- #if defined(USE_MSRPC) && !defined(NO_PRIVATE_IP_DETECT)
- if (PublicIPProtectionLevel)
- {
- printerrorf("Warning: Public IP address protection using MS RPC is poor. See vlmcsd.8\n");
- }
- #endif // defined(USE_MSRPC) && !defined(NO_PRIVATE_IP_DETECT)
- #if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__ && !defined(USE_MSRPC)
- allocateSemaphore();
- #endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && __minix__
- #ifdef _NTSERVICE
- if (installService)
- return NtServiceInstallation(installService, ServiceUser, ServicePassword);
- #endif // _NTSERVICE
- #if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- if (!InetdMode)
- {
- #ifdef SIMPLE_SOCKETS
- if ((error = listenOnAllAddresses())) return error;
- #else // !SIMPLE_SOCKETS
- if ((error = setupListeningSockets())) return error;
- #endif // !SIMPLE_SOCKETS
- }
- #endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- // After sockets have been set up, we may switch to a lower privileged user
- #if !defined(_WIN32) && !defined(NO_USER_SWITCH)
- #ifndef NO_SIGHUP
- if (!IsRestarted)
- {
- #endif // NO_SIGHUP
- if (gid != INVALID_GID)
- {
- if (setgid(gid))
- {
- printerrorf("Fatal: %s for %s failed: %s\n", "setgid", gname, strerror(errno));
- return errno;
- }
- if (setgroups(1, &gid))
- {
- printerrorf("Fatal: %s for %s failed: %s\n", "setgroups", gname, strerror(errno));
- return errno;
- }
- }
- if (uid != INVALID_UID && setuid(uid))
- {
- printerrorf("Fatal: %s for %s failed: %s\n", "setuid", uname, strerror(errno));
- return errno;
- }
- #ifndef NO_SIGHUP
- }
- #endif // NO_SIGHUP
- #endif // !defined(_WIN32) && !defined(NO_USER_SWITCH)
- randomNumberInit();
- // Randomization Level 1 means generate ePIDs at startup and use them during
- // the lifetime of the process. So we generate them now
- #ifndef NO_RANDOM_EPID
- if (RandomizationLevel == 1) randomPidInit();
- #endif
- #if !defined(NO_SOCKETS)
- #ifdef _WIN32
- if (!IsNTService)
- #endif // _WIN32
- if ((error = daemonizeAndSetSignalAction())) return error;
- #endif // !defined(NO_SOCKETS)
- writePidFile();
- #if !defined(NO_LOG) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- if (!InetdMode)
- logger("vlmcsd %s started successfully\n", Version);
- #endif // !defined(NO_LOG) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- #if defined(_NTSERVICE) && !defined(USE_MSRPC)
- if (IsNTService) ReportServiceStatus(SERVICE_RUNNING, NO_ERROR, 200);
- #endif // defined(_NTSERVICE) && !defined(USE_MSRPC)
- int rc;
- rc = runServer();
- // Clean up things and exit
- #ifdef _NTSERVICE
- if (!ServiceShutdown)
- #endif
- cleanup();
- #ifdef _NTSERVICE
- else
- ReportServiceStatus(SERVICE_STOPPED, NO_ERROR, 0);
- #endif
- return rc;
- }
|