Merge pull request #38 from rouben/master

vlmcsd-1113-2020-03-28-Hotbird64
pull/40/head
Rouben 5 years ago committed by GitHub
commit 5b08c8f2a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -225,9 +225,9 @@ help:
@echo " DNS_PARSER=internal Use $(BASE_CLIENT_NAME) internal DNS parsing routines. No effect on MingW (native Windows)." @echo " DNS_PARSER=internal Use $(BASE_CLIENT_NAME) internal DNS parsing routines. No effect on MingW (native Windows)."
@echo "" @echo ""
@echo "Other useful CFLAGS" @echo "Other useful CFLAGS"
@echo " -DNO_COMPILER_UAA Do not use compiler support for byte swapping and unaligned access"
@echo " -DFULL_INTERNAL_DATA Embed full internal KMS data in $(BASE_PROGRAM_NAME)." @echo " -DFULL_INTERNAL_DATA Embed full internal KMS data in $(BASE_PROGRAM_NAME)."
@echo " -DSUPPORT_WINE Add code that the Windows version of $(BASE_PROGRAM_NAME) runs on Wine if MSRPC=1" @echo " -DSUPPORT_WINE Add code that the Windows version of $(BASE_PROGRAM_NAME) runs on Wine if MSRPC=1"
@echo " -D_PEDANTIC Report rare error/warning conditions instead of silently ignoring them." @echo " -D_PEDANTIC Report rare error/warning conditions instead of silently ignoring them."
@echo " -DINCLUDE_BETAS Include SKU / activation IDs for obsolete beta/preview products."
@echo " -DFD_SETSIZE=<x> Allow <x> -L statements in $(BASE_PROGRAM_NAME) (default: 64 on Windows, 1024 on most Unixes)." @echo " -DFD_SETSIZE=<x> Allow <x> -L statements in $(BASE_PROGRAM_NAME) (default: 64 on Windows, 1024 on most Unixes)."

Binary file not shown.

@ -1,5 +1,5 @@
.mso www.tmac .mso www.tmac
.TH "VLMCSD-FLOPPY" 7 "May 2017" "Hotbird64" "KMS Activation Manual" .TH "VLMCSD-FLOPPY" 7 "February 2019" "Hotbird64" "KMS Activation Manual"
.LO 8 .LO 8
.SH NAME .SH NAME
@ -107,6 +107,9 @@ Defines the ePID that is used for Office 2016 activations. If you ommit this par
.IP "\fBOFFICE2016=\fIepid\fR" .IP "\fBOFFICE2016=\fIepid\fR"
Defines the ePID that is used for Office 2016 activations. If you ommit this parameter, \fBvlmcsd\fR(8) generates a random ePID when it is started. Defines the ePID that is used for Office 2016 activations. If you ommit this parameter, \fBvlmcsd\fR(8) generates a random ePID when it is started.
.IP "\fBOFFICE2019=\fIepid\fR"
Defines the ePID that is used for Office 2019 activations. If you ommit this parameter, \fBvlmcsd\fR(8) generates a random ePID when it is started.
.IP "\fBWINCHINAGOV=\fIepid\fR" .IP "\fBWINCHINAGOV=\fIepid\fR"
Defines the ePID that is used for Windows China Government Edition activations (Enterprise G/GN). If you ommit this parameter, \fBvlmcsd\fR(8) generates a random ePID when it is started. Defines the ePID that is used for Windows China Government Edition activations (Enterprise G/GN). If you ommit this parameter, \fBvlmcsd\fR(8) generates a random ePID when it is started.

@ -1,5 +1,5 @@
.mso www.tmac .mso www.tmac
.TH VLMCSD 8 "October 2018" "Hotbird64" "KMS Activation Manual" .TH VLMCSD 8 "February 2019" "Hotbird64" "KMS Activation Manual"
.LO 8 .LO 8
.SH NAME .SH NAME
@ -312,9 +312,9 @@ Signaling is not available in the native Windows version and in the Cygwin versi
\fBvlmcsd\fR compiles and runs on Linux, Windows (no Cygwin required but explicitly supported), Mac OS X, FreeBSD, NetBSD, OpenBSD, Dragonfly BSD, Minix, Solaris, OpenIndiana, Android and iOS. Other POSIX or unixoid OSses may work with unmodified sources or may require minor porting efforts. \fBvlmcsd\fR compiles and runs on Linux, Windows (no Cygwin required but explicitly supported), Mac OS X, FreeBSD, NetBSD, OpenBSD, Dragonfly BSD, Minix, Solaris, OpenIndiana, Android and iOS. Other POSIX or unixoid OSses may work with unmodified sources or may require minor porting efforts.
.SH SUPPORTED PRODUCTS .SH SUPPORTED PRODUCTS
\fBvlmcsd\fR can answer activation requests for the following products: Windows Vista, Windows 7, Windows 8, Windows 8.1, Windows 10 (up to 1703), Windows Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows Server 2012 R2, Windows Server 2016, Office 2010, Project 2010, Visio 2010, Office 2013, Project 2013, Visio 2013, Office 2016, Project 2016, Visio 2016. Newer products may work as long as the KMS protocol does not change. A complete list of fully supported products can be obtained using the \fB-x\fR option of \fBvlmcs\fR(1). \fBvlmcsd\fR can answer activation requests for the following products: Windows Vista, Windows 7, Windows 8, Windows 8.1, Windows 10 (up to 1809), Windows Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows Server 2012 R2, Windows Server 2016, Office 2010, Project 2010, Visio 2010, Office 2013, Project 2013, Visio 2013, Office 2016, Project 2016, Visio 2016, Office 2019, Project 2019, Visio 2019. Newer products may work as long as the KMS protocol does not change. A complete list of fully supported products can be obtained using the \fB-x\fR option of \fBvlmcs\fR(1).
.PP .PP
Office, Project and Visio must be volume license versions. Windows Vista, Windows 7, Office, Project and Visio must be volume license versions.
.SH FILES .SH FILES
.IP "\fBvlmcsd.ini\fR(5)" .IP "\fBvlmcsd.ini\fR(5)"

@ -6,7 +6,7 @@
#include "endian.h" #include "endian.h"
#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \ #if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \
&& defined(BS16) && defined(BS32) && defined(BS64) && defined(BS16) && defined(BS32) && defined(BS64) && !defined(NO_COMPILER_UAA)
#else // ! defined(__BYTE_ORDER) #else // ! defined(__BYTE_ORDER)
@ -136,8 +136,12 @@ unsigned short GET_UAA16LE(void *p, unsigned int i)
(unsigned short)_p[ 0 ] | (unsigned short)_p[ 0 ] |
(unsigned short)_p[ 1 ] << 8; (unsigned short)_p[ 1 ] << 8;
} }
#endif
#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \
&& defined(BS16) && defined(BS32) && defined(BS64)
#else
unsigned short BE16(unsigned short x) unsigned short BE16(unsigned short x)
{ {
return GET_UAA16BE(&x, 0); return GET_UAA16BE(&x, 0);

@ -9,17 +9,17 @@
// //
// Unaligned access // Unaligned access
// //
#if !defined(NO_COMPILER_UAA)
#define UAA16(p, i) (((PACKED16*)p)->val[i]) #define UAA16(p, i) (((PACKED16*)p)->val[i])
#define UAA32(p, i) (((PACKED32*)p)->val[i]) #define UAA32(p, i) (((PACKED32*)p)->val[i])
#define UAA64(p, i) (((PACKED64*)p)->val[i]) #define UAA64(p, i) (((PACKED64*)p)->val[i])
#endif
#define UA64(p) UAA64(p, 0)
#define UA32(p) UAA32(p, 0)
#define UA16(p) UAA16(p, 0)
// //
//Byteswap: Use compiler support if available //Byteswap: Use compiler support if available
// //
#ifndef NO_COMPILER_UAA
#ifdef __has_builtin // Clang supports this #ifdef __has_builtin // Clang supports this
#if __has_builtin(__builtin_bswap16) #if __has_builtin(__builtin_bswap16)
@ -56,6 +56,7 @@
#endif // GNU C > 4.7 #endif // GNU C > 4.7
#endif // __GNUC__ > 4 #endif // __GNUC__ > 4
#endif // __GNUC__ #endif // __GNUC__
#endif // NO_COMPILER_UAA
// //
// Byteorder // Byteorder
@ -198,6 +199,10 @@
#define __BE64(x) BS64(x) #define __BE64(x) BS64(x)
#define __LE64(x) (x) #define __LE64(x) (x)
#define PUT_UA16(p, v) PUT_UA16LE(p, v)
#define PUT_UA32(p, v) PUT_UA32LE(p, v)
#define PUT_UA64(p, v) PUT_UA64LE(p, v)
#else // __BYTE_ORDER == __BIG_ENDIAN #else // __BYTE_ORDER == __BIG_ENDIAN
#define __BE16(x) (x) #define __BE16(x) (x)
@ -207,8 +212,38 @@
#define __BE64(x) (x) #define __BE64(x) (x)
#define __LE64(x) BS64(x) #define __LE64(x) BS64(x)
#define PUT_UA16(p, v) PUT_UA16BE(p, v)
#define PUT_UA32(p, v) PUT_UA32BE(p, v)
#define PUT_UA64(p, v) PUT_UA64BE(p, v)
#endif // __BYTE_ORDER #endif // __BYTE_ORDER
#define BE16(x) __BE16(x)
#define LE16(x) __LE16(x)
#define BE32(x) __BE32(x)
#define LE32(x) __LE32(x)
#define BE64(x) __BE64(x)
#define LE64(x) __LE64(x)
#else
extern unsigned short BE16(unsigned short x);
extern unsigned short LE16(unsigned short x);
extern unsigned int BE32(unsigned int x);
extern unsigned int LE32(unsigned int x);
extern unsigned long long BE64(unsigned long long x);
extern unsigned long long LE64(unsigned long long x);
#endif // defined(__BYTE_ORDER)
#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \
&& defined(BS16) && defined(BS32) && defined(BS64) &&!defined(NO_COMPILER_UAA)
#define PUT_UAA64BE(p, v, i) ( UAA64(p, i) = __BE64(v) ) #define PUT_UAA64BE(p, v, i) ( UAA64(p, i) = __BE64(v) )
#define PUT_UAA32BE(p, v, i) ( UAA32(p, i) = __BE32(v) ) #define PUT_UAA32BE(p, v, i) ( UAA32(p, i) = __BE32(v) )
#define PUT_UAA16BE(p, v, i) ( UAA16(p, i) = __BE16(v) ) #define PUT_UAA16BE(p, v, i) ( UAA16(p, i) = __BE16(v) )
@ -225,56 +260,37 @@
#define GET_UAA32LE(p, i) __LE32(UAA32(p, i)) #define GET_UAA32LE(p, i) __LE32(UAA32(p, i))
#define GET_UAA16LE(p, i) __LE16(UAA16(p, i)) #define GET_UAA16LE(p, i) __LE16(UAA16(p, i))
#define BE16(x) __BE16(x)
#define LE16(x) __LE16(x)
#define BE32(x) __BE32(x)
#define LE32(x) __LE32(x)
#define BE64(x) __BE64(x)
#define LE64(x) __LE64(x)
#else // ! defined(__BYTE_ORDER) #else // ! defined(__BYTE_ORDER)
extern void PUT_UAA64BE(void *p, unsigned long long v, unsigned int i); extern void PUT_UAA64BE(void* p, unsigned long long v, unsigned int i);
extern void PUT_UAA32BE(void *p, unsigned int v, unsigned int i); extern void PUT_UAA32BE(void* p, unsigned int v, unsigned int i);
extern void PUT_UAA16BE(void *p, unsigned short v, unsigned int i); extern void PUT_UAA16BE(void* p, unsigned short v, unsigned int i);
extern void PUT_UAA64LE(void *p, unsigned long long v, unsigned int i); extern void PUT_UAA64LE(void* p, unsigned long long v, unsigned int i);
extern void PUT_UAA32LE(void *p, unsigned int v, unsigned int i); extern void PUT_UAA32LE(void* p, unsigned int v, unsigned int i);
extern void PUT_UAA16LE(void *p, unsigned short v, unsigned int i); extern void PUT_UAA16LE(void* p, unsigned short v, unsigned int i);
extern unsigned long long GET_UAA64BE(void *p, unsigned int i); extern unsigned long long GET_UAA64BE(void* p, unsigned int i);
extern unsigned int GET_UAA32BE(void *p, unsigned int i); extern unsigned int GET_UAA32BE(void* p, unsigned int i);
extern unsigned short GET_UAA16BE(void *p, unsigned int i); extern unsigned short GET_UAA16BE(void* p, unsigned int i);
extern unsigned long long GET_UAA64LE(void *p, unsigned int i); extern unsigned long long GET_UAA64LE(void* p, unsigned int i);
extern unsigned int GET_UAA32LE(void *p, unsigned int i); extern unsigned int GET_UAA32LE(void* p, unsigned int i);
extern unsigned short GET_UAA16LE(void *p, unsigned int i); extern unsigned short GET_UAA16LE(void* p, unsigned int i);
#endif
extern unsigned short BE16(unsigned short x);
extern unsigned short LE16(unsigned short x);
extern unsigned int BE32(unsigned int x);
extern unsigned int LE32(unsigned int x);
extern unsigned long long BE64(unsigned long long x);
extern unsigned long long LE64(unsigned long long x);
#endif // defined(__BYTE_ORDER)
#define PUT_UA64BE(p, v) PUT_UAA64BE(p, v, 0) #define PUT_UA64BE(p, v) PUT_UAA64BE(p, v, 0)

@ -434,14 +434,14 @@ __pure BOOL getArgumentBool(int_fast8_t *result, const char *const argument)
#ifndef NO_EXTERNAL_DATA #ifndef NO_EXTERNAL_DATA
__noreturn static void dataFileReadError() __noreturn static void dataFileReadError()
{ {
int error = errno; const int error = errno;
errorout("Fatal: Could not read %s: %s\n", fn_data, strerror(error)); errorout("Fatal: Could not read %s: %s\n", fn_data, strerror(error));
exit(error); exit(error);
} }
__noreturn static void dataFileFormatError() __noreturn static void dataFileFormatError()
{ {
errorout("Fatal: %s is not a KMS data file\n", fn_data); errorout("Fatal: %s is not a KMS data file version 2.x\n", fn_data);
exit(VLMCSD_EINVAL); exit(VLMCSD_EINVAL);
} }
#endif // NO_EXTERNAL_DATA #endif // NO_EXTERNAL_DATA
@ -526,7 +526,7 @@ static void getDefaultDataFile()
getExeName(); getExeName();
strncpy(fileName, fn_exe, MAX_PATH); strncpy(fileName, fn_exe, MAX_PATH);
PathRemoveFileSpec(fileName); PathRemoveFileSpec(fileName);
strncat(fileName, "\\vlmcsd.kmd", MAX_PATH); strncat(fileName, "\\vlmcsd.kmd", MAX_PATH - 11);
fn_data = vlmcsd_strdup(fileName); fn_data = vlmcsd_strdup(fileName);
} }
#else // !_WIN32 #else // !_WIN32
@ -588,12 +588,12 @@ void loadKmsData()
KmsData = (PVlmcsdHeader_t)vlmcsd_malloc(size); KmsData = (PVlmcsdHeader_t)vlmcsd_malloc(size);
if (fseek(file, 0, SEEK_SET)) dataFileReadError(); if (fseek(file, 0, SEEK_SET)) dataFileReadError();
size_t bytesRead = fread(KmsData, 1, size, file); const size_t bytesRead = fread(KmsData, 1, size, file);
if ((long)bytesRead != size) dataFileReadError(); if ((long)bytesRead != size) dataFileReadError();
fclose(file); fclose(file);
# if !defined(NO_LOG) && !defined(NO_SOCKETS) # if !defined(NO_LOG) && !defined(NO_SOCKETS)
if (!InetdMode) logger("Read KMS data file version %u.%u %s\n", (unsigned int)KmsData->MajorVer, (unsigned int)KmsData->MinorVer, fn_data); if (!InetdMode) logger("Read KMS data file version %u.%u %s\n", (unsigned int)LE16(KmsData->MajorVer), (unsigned int)LE16(KmsData->MinorVer), fn_data);
# endif // NO_LOG # endif // NO_LOG
} }
} }
@ -610,6 +610,7 @@ void loadKmsData()
KmsData->AppItemCount = LE32(KmsData->AppItemCount); KmsData->AppItemCount = LE32(KmsData->AppItemCount);
KmsData->KmsItemCount = LE32(KmsData->KmsItemCount); KmsData->KmsItemCount = LE32(KmsData->KmsItemCount);
KmsData->SkuItemCount = LE32(KmsData->SkuItemCount); KmsData->SkuItemCount = LE32(KmsData->SkuItemCount);
KmsData->HostBuildCount = LE32(KmsData->HostBuildCount);
uint32_t i; uint32_t i;
@ -625,6 +626,7 @@ void loadKmsData()
{ {
PCsvlkData_t csvlkData = &KmsData->CsvlkData[i]; PCsvlkData_t csvlkData = &KmsData->CsvlkData[i];
csvlkData->EPid = (char*)KmsData + LE64(csvlkData->EPidOffset); csvlkData->EPid = (char*)KmsData + LE64(csvlkData->EPidOffset);
csvlkData->ReleaseDate = LE64(csvlkData->ReleaseDate);
# ifndef UNSAFE_DATA_LOAD # ifndef UNSAFE_DATA_LOAD
if (csvlkData->EPid > (char*)KmsData + size) dataFileFormatError(); if (csvlkData->EPid > (char*)KmsData + size) dataFileFormatError();
# endif // UNSAFE_DATA_LOAD # endif // UNSAFE_DATA_LOAD
@ -636,12 +638,25 @@ void loadKmsData()
# endif // NO_RANDOM_EPID # endif // NO_RANDOM_EPID
} }
for (i = 0; i < (uint32_t)KmsData->HostBuildCount; i++)
{
PHostBuild_t hostBuild = &KmsData->HostBuildList[i];
hostBuild->BuildNumber = LE32(hostBuild->BuildNumber);
hostBuild->Flags = LE32(hostBuild->Flags);
hostBuild->PlatformId = LE32(hostBuild->PlatformId);
hostBuild->ReleaseDate = LE64(hostBuild->ReleaseDate);
hostBuild->DisplayName = (char*)KmsData + LE64(hostBuild->DisplayNameOffset);
# ifndef UNSAFE_DATA_LOAD
if (hostBuild->DisplayName > (char*)KmsData + size) dataFileFormatError();
# endif // UNSAFE_DATA_LOAD
}
const uint32_t totalItemCount = KmsData->AppItemCount + KmsData->KmsItemCount + KmsData->SkuItemCount; const uint32_t totalItemCount = KmsData->AppItemCount + KmsData->KmsItemCount + KmsData->SkuItemCount;
# ifndef NO_EXTERNAL_DATA # ifndef NO_EXTERNAL_DATA
if ( if (
memcmp(KmsData->Magic, "KMD", sizeof(KmsData->Magic)) || memcmp(KmsData->Magic, "KMD", sizeof(KmsData->Magic)) ||
KmsData->MajorVer != 1 KmsData->MajorVer != 2
# ifndef UNSAFE_DATA_LOAD # ifndef UNSAFE_DATA_LOAD
|| ||
sizeof(VlmcsdHeader_t) + totalItemCount * sizeof(VlmcsdData_t) >= ((uint64_t)size) sizeof(VlmcsdHeader_t) + totalItemCount * sizeof(VlmcsdData_t) >= ((uint64_t)size)

@ -57,16 +57,23 @@ int32_t getProductIndex(const GUID* guid, const PVlmcsdData_t list, const int32_
} }
} }
if (name) *name = "Unknown"; if (name) *name = (char*)"Unknown";
if (ePid) *ePid = KmsData->CsvlkData[EPID_INDEX_WINDOWS].EPid; if (ePid) *ePid = KmsData->CsvlkData->EPid;
return i; return i;
} }
#if !defined(NO_INI_FILE)||!defined(NO_VERBOSE_LOG)
const char* getNextString(const char* s)
{
return s + strlen(s) + 1;
}
#endif //!defined(NO_INI_FILE)||!defined(NO_VERBOSE_LOG)
#endif // IS_LIBRARY #endif // IS_LIBRARY
#ifndef NO_RANDOM_EPID #ifndef NO_RANDOM_EPID
static const uint16_t HostBuilds[] = { 6002, 7601, 9200, 9600, 14393, 17763 }; //static const uint16_t HostBuilds[] = { 6002, 7601, 9200, 9600, 14393, 17763 };
// Valid language identifiers to be used in the ePID // Valid language identifiers to be used in the ePID
static const uint16_t LcidList[] = { static const uint16_t LcidList[] = {
@ -80,14 +87,38 @@ static const uint16_t LcidList[] = {
17418, 18442, 19466, 20490, 1089, 1053, 2077, 1114, 1097, 1092, 1098, 1054, 1074, 1058, 1056, 1091, 2115, 1066, 1106, 1076, 1077 17418, 18442, 19466, 20490, 1089, 1053, 2077, 1114, 1097, 1092, 1098, 1054, 1074, 1058, 1056, 1091, 2115, 1066, 1106, 1076, 1077
}; };
uint16_t getPlatformId(uint16_t hostBuild) int32_t getPlatformId(int32_t hostBuild)
{ {
if (hostBuild < 9000) return 55041; int32_t i;
if (hostBuild <= 9500) return 5426;
if (hostBuild <= 10000) return 6401; for (i = 0; i < KmsData->HostBuildCount; i++)
return 3612; {
if (KmsData->HostBuildList[i].BuildNumber <= hostBuild)
{
return KmsData->HostBuildList[i].PlatformId;
}
}
return KmsData->HostBuildList[KmsData->HostBuildCount - 1].PlatformId;
}
time_t getReleaseDate(int32_t hostBuild)
{
int32_t i;
for (i = KmsData->HostBuildCount - 1; i >= 0; i--)
{
if (KmsData->HostBuildList[i].BuildNumber >= hostBuild)
{
return (time_t)KmsData->HostBuildList[i].ReleaseDate;
}
}
return (time_t)KmsData->HostBuildList->ReleaseDate;
} }
#ifdef _PEDANTIC #ifdef _PEDANTIC
uint16_t IsValidLcid(const uint16_t lcid) uint16_t IsValidLcid(const uint16_t lcid)
{ {
@ -102,13 +133,13 @@ uint16_t IsValidLcid(const uint16_t lcid)
} }
uint16_t IsValidHostBuild(const uint16_t hostBuild) uint32_t IsValidHostBuild(const int32_t hostBuild)
{ {
const uint16_t *hostOS; PHostBuild_t hostOS;
for (hostOS = HostBuilds; hostOS < HostBuilds + vlmcsd_countof(HostBuilds); hostOS++) for (hostOS = KmsData->HostBuildList; hostOS < KmsData->HostBuildList + KmsData->HostBuildCount; hostOS++)
{ {
if (hostBuild == *hostOS) return hostBuild; if (hostBuild == hostOS->BuildNumber) return hostBuild;
} }
return 0; return 0;
@ -119,7 +150,7 @@ uint16_t IsValidHostBuild(const uint16_t hostBuild)
// Unix time is seconds from 1970-01-01. Should be 64 bits to avoid year 2038 overflow bug. // Unix time is seconds from 1970-01-01. Should be 64 bits to avoid year 2038 overflow bug.
// FILETIME is 100 nanoseconds from 1601-01-01. Must be 64 bits. // FILETIME is 100 nanoseconds from 1601-01-01. Must be 64 bits.
void getUnixTimeAsFileTime(FILETIME *const ts) void getUnixTimeAsFileTime(FILETIME* ts)
{ {
const int64_t unixtime = (int64_t)time(NULL); const int64_t unixtime = (int64_t)time(NULL);
int64_t *filetime = (int64_t*)ts; int64_t *filetime = (int64_t*)ts;
@ -127,7 +158,7 @@ void getUnixTimeAsFileTime(FILETIME *const ts)
PUT_UA64LE(filetime, (unixtime + 11644473600LL) * 10000000LL); PUT_UA64LE(filetime, (unixtime + 11644473600LL) * 10000000LL);
} }
__pure int64_t fileTimeToUnixTime(const FILETIME *const ts) __pure int64_t fileTimeToUnixTime(FILETIME* ts)
{ {
return GET_UA64LE(ts) / 10000000LL - 11644473600LL; return GET_UA64LE(ts) / 10000000LL - 11644473600LL;
} }
@ -255,19 +286,18 @@ static uint8_t getRandomServerType()
{ {
# if defined(USE_MSRPC) || defined(SIMPLE_RPC) # if defined(USE_MSRPC) || defined(SIMPLE_RPC)
return rand() % vlmcsd_countof(HostBuilds); return rand() % KmsData->HostBuildCount;
# else // !defined(USE_MSRPC) && !defined(SIMPLE_RPC) # else // !defined(USE_MSRPC) && !defined(SIMPLE_RPC)
if (!UseServerRpcBTFN) while (TRUE)
{ {
// This isn't possible at all, e.g. KMS host on XP const uint32_t buildIndex = rand() % KmsData->HostBuildCount;
return rand() % (int)vlmcsd_countof(HostBuilds);
}
// return 9200/9600/14393/17763 if NDR64 is in use, otherwise 6002/7601
if (UseServerRpcNDR64) return rand() % ((int)vlmcsd_countof(HostBuilds) - 2) + 2;
return rand() % 2;
if (!(KmsData->HostBuildList[buildIndex].Flags & UseNdr64) == !UseServerRpcNDR64)
{
return (uint8_t)buildIndex;
}
}
# endif // !defined(USE_MSRPC) && !defined(SIMPLE_RPC) # endif // !defined(USE_MSRPC) && !defined(SIMPLE_RPC)
} }
@ -275,13 +305,13 @@ static uint8_t getRandomServerType()
/* /*
* Generates a random ePID * Generates a random ePID
*/ */
static void generateRandomPid(const int index, char *const szPid, int16_t lang, uint16_t hostBuild) static void generateRandomPid(const int index, char *const szPid, int16_t lang, int32_t hostBuild)
{ {
char numberBuffer[12]; char numberBuffer[12];
if (!hostBuild) if (!hostBuild)
{ {
hostBuild = HostBuilds[getRandomServerType()]; hostBuild = KmsData->HostBuildList[getRandomServerType()].BuildNumber;
} }
@ -290,7 +320,7 @@ static void generateRandomPid(const int index, char *const szPid, int16_t lang,
//if (index > 3) index = 0; //if (index > 3) index = 0;
const PCsvlkData_t csvlkData = &KmsData->CsvlkData[index]; PCsvlkData_t csvlkData = &KmsData->CsvlkData[index];
strcat(szPid, itoc(numberBuffer, csvlkData->GroupId, 5)); strcat(szPid, itoc(numberBuffer, csvlkData->GroupId, 5));
strcat(szPid, "-"); strcat(szPid, "-");
@ -307,7 +337,8 @@ static void generateRandomPid(const int index, char *const szPid, int16_t lang,
strcat(szPid, itoc(numberBuffer, hostBuild, 0)); strcat(szPid, itoc(numberBuffer, hostBuild, 0));
strcat(szPid, ".0000-"); strcat(szPid, ".0000-");
# define minTime ((time_t)1538490811) /* Release Date Win 2019 */ const time_t hostBuildReleaseDate = getReleaseDate(hostBuild);
const time_t minTime = csvlkData->ReleaseDate < hostBuildReleaseDate ? hostBuildReleaseDate : csvlkData->ReleaseDate;
time_t maxTime; time_t maxTime;
time(&maxTime); time(&maxTime);
@ -343,11 +374,33 @@ void randomPidInit()
char Epid[PID_BUFFER_SIZE]; char Epid[PID_BUFFER_SIZE];
if (!HostBuild)
{
uint8_t index;
#if defined(USE_MSRPC) || defined(SIMPLE_RPC)
index = getRandomServerType();
#else // !(defined(USE_MSRPC) || defined(SIMPLE_RPC))
if (IsNDR64Defined)
{
index = getRandomServerType();
}
else
{
index = (uint8_t)(rand() % KmsData->HostBuildCount);
UseServerRpcNDR64 = !!(KmsData->HostBuildList[index].Flags & UseNdr64);
}
#endif // !(defined(USE_MSRPC) || defined(SIMPLE_RPC))
HostBuild = (uint16_t)KmsData->HostBuildList[index].BuildNumber;
}
generateRandomPid(i, Epid, lang, HostBuild); generateRandomPid(i, Epid, lang, HostBuild);
KmsResponseParameters[i].Epid = (const char*)vlmcsd_strdup(Epid); KmsResponseParameters[i].Epid = (const char*)vlmcsd_strdup(Epid);
#ifndef NO_LOG #ifndef NO_LOG
KmsResponseParameters[i].EpidSource = "randomized at program start"; KmsResponseParameters[i].EpidSource = "randomized at program start";
KmsResponseParameters[i].IsRandom = TRUE;
#endif // NO_LOG #endif // NO_LOG
} }
} }
@ -364,7 +417,7 @@ static int32_t getProductIndexFromAllLists(const GUID* guid, char** productName)
/* /*
* Logs a Request * Logs a Request
*/ */
static void logRequest(const REQUEST *const baseRequest) static void logRequest(REQUEST* baseRequest)
{ {
#ifndef NO_VERBOSE_LOG #ifndef NO_VERBOSE_LOG
if (logverbose) if (logverbose)
@ -376,7 +429,7 @@ static void logRequest(const REQUEST *const baseRequest)
#endif // NO_VERBOSE_LOG #endif // NO_VERBOSE_LOG
char *productName; char *productName;
char clientname[64]; char clientName[64];
int32_t index = getProductIndexFromAllLists(&baseRequest->ActID, &productName); int32_t index = getProductIndexFromAllLists(&baseRequest->ActID, &productName);
if (index < 0) index = getProductIndexFromAllLists(&baseRequest->KMSID, &productName); if (index < 0) index = getProductIndexFromAllLists(&baseRequest->KMSID, &productName);
@ -388,8 +441,8 @@ static void logRequest(const REQUEST *const baseRequest)
uuid2StringLE(&baseRequest->ActID, productName); uuid2StringLE(&baseRequest->ActID, productName);
} }
ucs2_to_utf8(baseRequest->WorkstationName, clientname, 64, 64); ucs2_to_utf8(baseRequest->WorkstationName, clientName, 64, 64);
logger("KMS v%i.%i request from %s for %s\n", LE16(baseRequest->MajorVer), LE16(baseRequest->MinorVer), clientname, productName); logger("KMS v%i.%i request from %s for %s\n", LE16(baseRequest->MajorVer), LE16(baseRequest->MinorVer), clientName, productName);
} }
#endif // NO_LOG #endif // NO_LOG
@ -493,7 +546,7 @@ static void CheckRequest(const REQUEST *const Request)
/* /*
* Logs the Response * Logs the Response
*/ */
static void logResponse(const RESPONSE *const baseResponse, const BYTE *const hwId, const char *const EpidSource) static void logResponse(RESPONSE* baseResponse, const BYTE *const hwId, const char *const EpidSource)
{ {
char utf8pid[PID_BUFFER_SIZE * 3]; char utf8pid[PID_BUFFER_SIZE * 3];
ucs2_to_utf8(baseResponse->KmsPID, utf8pid, PID_BUFFER_SIZE, PID_BUFFER_SIZE * 3); ucs2_to_utf8(baseResponse->KmsPID, utf8pid, PID_BUFFER_SIZE, PID_BUFFER_SIZE * 3);
@ -525,7 +578,7 @@ long long int llabs(long long int j);
* Creates the unencrypted base response * Creates the unencrypted base response
*/ */
#ifndef IS_LIBRARY #ifndef IS_LIBRARY
static HRESULT __stdcall CreateResponseBaseCallback(const REQUEST *const baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr_unused) static HRESULT __stdcall CreateResponseBaseCallback(REQUEST* baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr_unused)
{ {
const char* EpidSource; const char* EpidSource;
#ifndef NO_LOG #ifndef NO_LOG
@ -539,7 +592,7 @@ static HRESULT __stdcall CreateResponseBaseCallback(const REQUEST *const baseReq
const DWORD minClients = LE32(baseRequest->N_Policy); const DWORD minClients = LE32(baseRequest->N_Policy);
const DWORD required_clients = minClients < 1 ? 1 : minClients << 1; const DWORD required_clients = minClients < 1 ? 1 : minClients << 1;
int32_t index = getProductIndex(&baseRequest->KMSID, KmsData->KmsItemList, KmsData->KmsItemCount, NULL, &ePid); const int32_t index = getProductIndex(&baseRequest->KMSID, KmsData->KmsItemList, KmsData->KmsItemCount, NULL, &ePid);
# ifndef NO_STRICT_MODES # ifndef NO_STRICT_MODES
@ -554,7 +607,7 @@ static HRESULT __stdcall CreateResponseBaseCallback(const REQUEST *const baseReq
if (CheckClientTime) if (CheckClientTime)
{ {
const time_t requestTime = (time_t)fileTimeToUnixTime(&baseRequest->ClientTime); time_t requestTime = (time_t)fileTimeToUnixTime(&baseRequest->ClientTime);
if (llabs(requestTime - time(NULL)) > 60 * 60 * 4) if (llabs(requestTime - time(NULL)) > 60 * 60 * 4)
{ {
@ -705,21 +758,21 @@ void get16RandomBytes(void* ptr)
/* /*
* Creates v4 response * Creates v4 response
*/ */
size_t CreateResponseV4(REQUEST_V4 *const request_v4, BYTE *const responseBuffer, const char* const ipstr) size_t CreateResponseV4(REQUEST_V4 *const request_v4, BYTE *const responseBuffer, const char* const ipString)
{ {
RESPONSE_V4* Response = (RESPONSE_V4*)responseBuffer; RESPONSE_V4* response = (RESPONSE_V4*)responseBuffer;
HRESULT hResult; HRESULT hResult;
if (FAILED(hResult = CreateResponseBase(&request_v4->RequestBase, &Response->ResponseBase, NULL, ipstr))) return hResult; if (FAILED(hResult = CreateResponseBase(&request_v4->RequestBase, &response->ResponseBase, NULL, ipString))) return hResult;
const DWORD pidSize = LE32(Response->ResponseBase.PIDSize); const DWORD pidSize = LE32(response->ResponseBase.PIDSize);
BYTE* postEpidPtr = responseBuffer + V4_PRE_EPID_SIZE + pidSize; BYTE* postEpidPtr = responseBuffer + V4_PRE_EPID_SIZE + pidSize;
memmove(postEpidPtr, &Response->ResponseBase.CMID, V4_POST_EPID_SIZE); memmove(postEpidPtr, &response->ResponseBase.CMID, V4_POST_EPID_SIZE);
const size_t encryptSize = V4_PRE_EPID_SIZE + V4_POST_EPID_SIZE + pidSize; const size_t encryptSize = V4_PRE_EPID_SIZE + V4_POST_EPID_SIZE + pidSize;
AesCmacV4(responseBuffer, encryptSize, responseBuffer + encryptSize); AesCmacV4(responseBuffer, encryptSize, responseBuffer + encryptSize);
return encryptSize + sizeof(Response->MAC); return encryptSize + sizeof(response->MAC);
} }
/* /*
@ -736,7 +789,7 @@ __pure static uint64_t TimestampInterval(void *ts)
/* /*
* Creates the HMAC for v6 * Creates the HMAC for v6
*/ */
static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptSize, int_fast8_t tolerance) static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptSize, const int_fast8_t tolerance)
{ {
BYTE hash[32]; BYTE hash[32];
const uint8_t halfHashSize = sizeof(hash) >> 1; const uint8_t halfHashSize = sizeof(hash) >> 1;
@ -746,7 +799,7 @@ static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptS
FILETIME* ft = (FILETIME*)(responseEnd - V6_POST_EPID_SIZE + sizeof(((RESPONSE*)0)->CMID)); FILETIME* ft = (FILETIME*)(responseEnd - V6_POST_EPID_SIZE + sizeof(((RESPONSE*)0)->CMID));
// Generate a time slot that changes every 4.11 hours. // Generate a time slot that changes every 4.11 hours.
// Request and repsonse time must match +/- 1 slot. // Request and response time must match +/- 1 slot.
// When generating a response tolerance must be 0. // When generating a response tolerance must be 0.
// If verifying the hash, try tolerance -1, 0 and +1. One of them must match. // If verifying the hash, try tolerance -1, 0 and +1. One of them must match.
@ -775,7 +828,7 @@ static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptS
/* /*
* Creates v5 or v6 response * Creates v5 or v6 response
*/ */
size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuffer, const char* const ipstr) size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuffer, const char* const ipString)
{ {
// The response will be created in a fixed sized struct to // The response will be created in a fixed sized struct to
// avoid unaligned access macros and packed structs on RISC systems // avoid unaligned access macros and packed structs on RISC systems
@ -784,15 +837,15 @@ size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuf
// The fixed sized struct with 64 WCHARs for the ePID will be converted // The fixed sized struct with 64 WCHARs for the ePID will be converted
// to a variable sized struct later and requires unaligned access macros. // to a variable sized struct later and requires unaligned access macros.
RESPONSE_V6* Response = (RESPONSE_V6*)responseBuffer; RESPONSE_V6* response = (RESPONSE_V6*)responseBuffer;
RESPONSE* baseResponse = &Response->ResponseBase; RESPONSE* baseResponse = &response->ResponseBase;
#ifdef _DEBUG #ifdef _DEBUG
// ReSharper disable once CppEntityNeverUsed // ReSharper disable once CppDeclaratorNeverUsed
RESPONSE_V6_DEBUG* xxx_unused = (RESPONSE_V6_DEBUG*)responseBuffer; RESPONSE_V6_DEBUG* xxx_unused = (RESPONSE_V6_DEBUG*)responseBuffer;
#endif #endif
static const BYTE DefaultHwid[8] = { HWID }; static const BYTE DefaultHwId[8] = { HWID };
const int_fast8_t v6 = LE16(request_v6->MajorVer) > 5; const int_fast8_t v6 = LE16(request_v6->MajorVer) > 5;
AesCtx aesCtx; AesCtx aesCtx;
@ -800,35 +853,35 @@ size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuf
AesDecryptCbc(&aesCtx, NULL, request_v6->IV, V6_DECRYPT_SIZE); AesDecryptCbc(&aesCtx, NULL, request_v6->IV, V6_DECRYPT_SIZE);
// get random salt and SHA256 it // get random salt and SHA256 it
get16RandomBytes(Response->RandomXoredIVs); get16RandomBytes(response->RandomXoredIVs);
Sha256(Response->RandomXoredIVs, sizeof(Response->RandomXoredIVs), Response->Hash); Sha256(response->RandomXoredIVs, sizeof(response->RandomXoredIVs), response->Hash);
if (v6) // V6 specific stuff if (v6) // V6 specific stuff
{ {
// In v6 a random IV is generated // In v6 a random IV is generated
Response->Version = request_v6->Version; response->Version = request_v6->Version;
get16RandomBytes(Response->IV); get16RandomBytes(response->IV);
// pre-fill with default HwId (not required for v5) // pre-fill with default HwId (not required for v5)
memcpy(Response->HwId, DefaultHwid, sizeof(Response->HwId)); memcpy(response->HwId, DefaultHwId, sizeof(response->HwId));
// Just copy decrypted request IV (using Null IV) here. Note this is identical // Just copy decrypted request IV (using Null IV) here. Note this is identical
// to XORing non-decrypted request and reponse IVs // to XORing non-decrypted request and response IVs
memcpy(Response->XoredIVs, request_v6->IV, sizeof(Response->XoredIVs)); memcpy(response->XoredIVs, request_v6->IV, sizeof(response->XoredIVs));
} }
else // V5 specific stuff else // V5 specific stuff
{ {
// In v5 IVs of request and response must be identical (MS client checks this) // In v5 IVs of request and response must be identical (MS client checks this)
// The following memcpy copies Version and IVs at once // The following memcpy copies Version and IVs at once
memcpy(Response, request_v6, V6_UNENCRYPTED_SIZE); memcpy(response, request_v6, V6_UNENCRYPTED_SIZE);
} }
// Xor Random bytes with decrypted request IV // Xor Random bytes with decrypted request IV
XorBlock(request_v6->IV, Response->RandomXoredIVs); XorBlock(request_v6->IV, response->RandomXoredIVs);
// Get the base response // Get the base response
HRESULT hResult; HRESULT hResult;
if (FAILED(hResult = CreateResponseBase(&request_v6->RequestBase, baseResponse, Response->HwId, ipstr))) return hResult; if (FAILED(hResult = CreateResponseBase(&request_v6->RequestBase, baseResponse, response->HwId, ipString))) return hResult;
// Convert the fixed sized struct into variable sized // Convert the fixed sized struct into variable sized
const DWORD pidSize = LE32(baseResponse->PIDSize); const DWORD pidSize = LE32(baseResponse->PIDSize);
@ -840,17 +893,17 @@ size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuf
// number of bytes to encrypt // number of bytes to encrypt
size_t encryptSize = size_t encryptSize =
V6_PRE_EPID_SIZE V6_PRE_EPID_SIZE
- sizeof(Response->Version) - sizeof(response->Version)
+ pidSize + pidSize
+ post_epid_size; + post_epid_size;
//AesDecryptBlock(&aesCtx, Response->IV); //AesDecryptBlock(&aesCtx, Response->IV);
if (v6 && !CreateV6Hmac(Response->IV, encryptSize, 0)) return 0; if (v6 && !CreateV6Hmac(response->IV, encryptSize, 0)) return 0;
// Padding auto handled by encryption func // Padding auto handled by encryption func
AesEncryptCbc(&aesCtx, NULL, Response->IV, &encryptSize); AesEncryptCbc(&aesCtx, NULL, response->IV, &encryptSize);
return encryptSize + sizeof(Response->Version); return encryptSize + sizeof(response->Version);
} }
@ -895,10 +948,10 @@ BYTE* CreateRequestV6(size_t *size, const REQUEST* requestBase)
// Encrypt KMS Client Request // Encrypt KMS Client Request
size_t encryptSize = sizeof(request->RequestBase); size_t encryptSize = sizeof(request->RequestBase);
AesCtx Ctx; AesCtx ctx;
int_fast8_t v6 = LE16(request->MajorVer) > 5; const int_fast8_t v6 = LE16(request->MajorVer) > 5;
AesInitKey(&Ctx, v6 ? AesKeyV6 : AesKeyV5, v6, 16); AesInitKey(&ctx, v6 ? AesKeyV6 : AesKeyV5, v6, 16);
AesEncryptCbc(&Ctx, request->IV, (BYTE*)(&request->RequestBase), &encryptSize); AesEncryptCbc(&ctx, request->IV, (BYTE*)(&request->RequestBase), &encryptSize);
// Return Proper Request Data // Return Proper Request Data
return (BYTE*)request; return (BYTE*)request;
@ -1045,11 +1098,11 @@ RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BY
// Decrypt KMS Server Response (encrypted part starts after RequestIV) // Decrypt KMS Server Response (encrypted part starts after RequestIV)
responseSize -= copySize1; responseSize -= copySize1;
AesCtx Ctx; AesCtx ctx;
const int_fast8_t v6 = LE16(((RESPONSE_V6*)response)->MajorVer) > 5; const int_fast8_t v6 = LE16(((RESPONSE_V6*)response)->MajorVer) > 5;
AesInitKey(&Ctx, v6 ? AesKeyV6 : AesKeyV5, v6, AES_KEY_BYTES); AesInitKey(&ctx, v6 ? AesKeyV6 : AesKeyV5, v6, AES_KEY_BYTES);
AesDecryptCbc(&Ctx, NULL, response + copySize1, responseSize); AesDecryptCbc(&ctx, NULL, response + copySize1, responseSize);
// Check padding // Check padding
BYTE* lastPadByte = response + (size_t)result.effectiveResponseSize - 1; BYTE* lastPadByte = response + (size_t)result.effectiveResponseSize - 1;
@ -1073,7 +1126,7 @@ RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BY
} }
// Add size of Version, KmsPIDLen and variable size PID // Add size of Version, KmsPIDLen and variable size PID
DWORD pidSize = LE32(((RESPONSE_V6*)response)->ResponseBase.PIDSize); const DWORD pidSize = LE32(((RESPONSE_V6*)response)->ResponseBase.PIDSize);
copySize1 += copySize1 +=
V6_UNENCRYPTED_SIZE + V6_UNENCRYPTED_SIZE +
@ -1097,9 +1150,9 @@ RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BY
REQUEST_V6* request_v6 = (REQUEST_V6*)rawRequest; REQUEST_V6* request_v6 = (REQUEST_V6*)rawRequest;
const DWORD decryptSize = sizeof(request_v6->IV) + sizeof(request_v6->RequestBase) + sizeof(request_v6->Pad); const DWORD decryptSize = sizeof(request_v6->IV) + sizeof(request_v6->RequestBase) + sizeof(request_v6->Pad);
AesDecryptCbc(&Ctx, NULL, request_v6->IV, decryptSize); AesDecryptCbc(&ctx, NULL, request_v6->IV, decryptSize);
// Check that all version informations are the same // Check that all version information is the same
result.VersionOK = result.VersionOK =
request_v6->Version == response_v6->ResponseBase.Version && request_v6->Version == response_v6->ResponseBase.Version &&
request_v6->Version == response_v6->Version && request_v6->Version == response_v6->Version &&
@ -1111,14 +1164,14 @@ RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BY
result.ClientMachineIDOK = IsEqualGUID(&response_v6->ResponseBase.CMID, &request_v6->RequestBase.CMID); result.ClientMachineIDOK = IsEqualGUID(&response_v6->ResponseBase.CMID, &request_v6->RequestBase.CMID);
// Rebuild Random Key and Sha256 Hash // Rebuild Random Key and Sha256 Hash
BYTE HashVerify[sizeof(response_v6->Hash)]; BYTE hashVerify[sizeof(response_v6->Hash)];
BYTE RandomKey[sizeof(response_v6->RandomXoredIVs)]; BYTE randomKey[sizeof(response_v6->RandomXoredIVs)];
memcpy(RandomKey, request_v6->IV, sizeof(RandomKey)); memcpy(randomKey, request_v6->IV, sizeof(randomKey));
XorBlock(response_v6->RandomXoredIVs, RandomKey); XorBlock(response_v6->RandomXoredIVs, randomKey);
Sha256(RandomKey, sizeof(RandomKey), HashVerify); Sha256(randomKey, sizeof(randomKey), hashVerify);
result.HashOK = !memcmp(response_v6->Hash, HashVerify, sizeof(HashVerify)); result.HashOK = !memcmp(response_v6->Hash, hashVerify, sizeof(hashVerify));
// size before encryption (padding not included) // size before encryption (padding not included)
result.correctResponseSize = result.correctResponseSize =

@ -228,6 +228,14 @@ typedef union
typedef BYTE hwid_t[8]; typedef BYTE hwid_t[8];
typedef enum
{
None = 0,
UseNdr64 = 1 << 0,
UseForEpid = 1 << 1,
MayBeServer = 1 << 2,
} HostBuildFlag;
typedef struct CsvlkData typedef struct CsvlkData
{ {
union union
@ -236,6 +244,7 @@ typedef struct CsvlkData
char* EPid; char* EPid;
}; };
int64_t ReleaseDate;
uint32_t GroupId; uint32_t GroupId;
uint32_t MinKeyId; uint32_t MinKeyId;
uint32_t MaxKeyId; uint32_t MaxKeyId;
@ -280,6 +289,22 @@ typedef struct
#define KMS_OPTIONS_USENDR64 1 << 0 #define KMS_OPTIONS_USENDR64 1 << 0
typedef struct HostBuild
{
union
{
uint64_t DisplayNameOffset;
char* DisplayName;
};
int64_t ReleaseDate;
int32_t BuildNumber;
int32_t PlatformId;
HostBuildFlag Flags;
uint8_t reserved[4];
} HostBuild_t, *PHostBuild_t;
typedef struct VlmcsdHeader typedef struct VlmcsdHeader
{ {
BYTE Magic[4]; BYTE Magic[4];
@ -290,19 +315,21 @@ typedef struct VlmcsdHeader
union union
{ {
int32_t Counts[3]; int32_t Counts[5];
struct struct
{ {
int32_t AppItemCount; int32_t AppItemCount;
int32_t KmsItemCount; int32_t KmsItemCount;
int32_t SkuItemCount; int32_t SkuItemCount;
int32_t HostBuildCount;
int32_t reserved2Counts;
}; };
}; };
union union
{ {
DataPointer_t Datapointers[3]; DataPointer_t Datapointers[5];
struct struct
{ {
@ -324,19 +351,31 @@ typedef struct VlmcsdHeader
PVlmcsdData_t SkuItemList; PVlmcsdData_t SkuItemList;
}; };
union
{
uint64_t HostBuildOffset;
PHostBuild_t HostBuildList;
};
union
{
uint64_t Reserved2Offset;
void* Reserved2List;
};
CsvlkData_t CsvlkData[1]; CsvlkData_t CsvlkData[1];
}; };
}; };
} VlmcsdHeader_t, *PVlmcsdHeader_t; } VlmcsdHeader_t, *PVlmcsdHeader_t;
#define EPID_INDEX_WINDOWS 0 //#define EPID_INDEX_WINDOWS 0
#define EPID_INDEX_OFFICE2010 1 //#define EPID_INDEX_OFFICE2010 1
#define EPID_INDEX_OFFICE2013 2 //#define EPID_INDEX_OFFICE2013 2
#define EPID_INDEX_OFFICE2016 3 //#define EPID_INDEX_OFFICE2016 3
#define EPID_INDEX_WINCHINAGOV 4 //#define EPID_INDEX_WINCHINAGOV 4
typedef HRESULT(__stdcall *RequestCallback_t)(const REQUEST *const baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr); typedef HRESULT(__stdcall *RequestCallback_t)(REQUEST* baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr);
size_t CreateResponseV4(REQUEST_V4 *const Request, BYTE *const response_data, const char* const ipstr); size_t CreateResponseV4(REQUEST_V4 *const Request, BYTE *const response_data, const char* const ipstr);
size_t CreateResponseV6(REQUEST_V6 *restrict Request, BYTE *const response_data, const char* const ipstr); size_t CreateResponseV6(REQUEST_V6 *restrict Request, BYTE *const response_data, const char* const ipstr);
@ -344,13 +383,16 @@ BYTE *CreateRequestV4(size_t *size, const REQUEST* requestBase);
BYTE *CreateRequestV6(size_t *size, const REQUEST* requestBase); BYTE *CreateRequestV6(size_t *size, const REQUEST* requestBase);
void randomPidInit(); void randomPidInit();
void get16RandomBytes(void* ptr); void get16RandomBytes(void* ptr);
RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* Response_v6, int responseSize, BYTE* const response, const BYTE* const request, BYTE* hwid); RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BYTE* const response, const BYTE* const rawRequest, BYTE* hwid);
RESPONSE_RESULT DecryptResponseV4(RESPONSE_V4* Response_v4, const int responseSize, BYTE* const response, const BYTE* const request); RESPONSE_RESULT DecryptResponseV4(RESPONSE_V4* response_v4, const int responseSize, BYTE* const rawResponse, const BYTE* const rawRequest);
void getUnixTimeAsFileTime(FILETIME *const ts); void getUnixTimeAsFileTime(FILETIME* ts);
__pure int64_t fileTimeToUnixTime(const FILETIME *const ts); __pure int64_t fileTimeToUnixTime(FILETIME* ts);
#ifndef IS_LIBRARY #ifndef IS_LIBRARY
int32_t getProductIndex(const GUID* guid, const PVlmcsdData_t list, const int32_t count, char** name, char** ePid); int32_t getProductIndex(const GUID* guid, const PVlmcsdData_t list, const int32_t count, char** name, char** ePid);
#if !defined(NO_INI_FILE)||!defined(NO_VERBOSE_LOG)
const char* getNextString(const char* s);
#endif // !defined(NO_INI_FILE)||!defined(NO_VERBOSE_LOG)
#endif // IS_LIBRARY #endif // IS_LIBRARY
#ifndef NO_STRICT_MODES #ifndef NO_STRICT_MODES
@ -362,7 +404,7 @@ extern RequestCallback_t CreateResponseBase;
#ifdef _PEDANTIC #ifdef _PEDANTIC
uint16_t IsValidLcid(const uint16_t lcid); uint16_t IsValidLcid(const uint16_t lcid);
uint16_t IsValidHostBuild(const uint16_t hostBuild); uint32_t IsValidHostBuild(const int32_t hostBuild);
#endif // _PEDANTIC #endif // _PEDANTIC
#endif // __kms_h #endif // __kms_h

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -171,7 +171,7 @@ RpcStatus closeRpc(const RpcCtx handle)
#if !MULTI_CALL_BINARY #if !MULTI_CALL_BINARY
// Memory allocation function for RPC. // Memory allocation function for RPC.
void *__RPC_USER midl_user_allocate(SIZE_T len) void *__RPC_USER midl_user_allocate(size_t len)
{ {
return vlmcsd_malloc(len); return vlmcsd_malloc(len);
} }

@ -294,7 +294,7 @@ int ProcessActivationRequest(handle_t IDL_handle, int requestSize, unsigned char
// Memory allocation function for RPC. // Memory allocation function for RPC.
void *__RPC_USER midl_user_allocate(SIZE_T len) void *__RPC_USER midl_user_allocate(size_t len)
{ {
return vlmcsd_malloc(len); return vlmcsd_malloc(len);
} }

@ -247,7 +247,7 @@ ns_name_unpack_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src
* Root domain returns as "." not "". * Root domain returns as "." not "".
*/ */
int int
ns_name_uncompress_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src, ns_name_uncompress_vlmcsd(uint8_t *msg, uint8_t *eom, uint8_t *src,
char *dst, size_t dstsiz) char *dst, size_t dstsiz)
{ {
uint8_t tmp[NS_MAXCDNAME]; uint8_t tmp[NS_MAXCDNAME];

@ -3,7 +3,7 @@
#define NS_NAME_H_ #define NS_NAME_H_
int int
ns_name_uncompress_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src, ns_name_uncompress_vlmcsd(uint8_t *msg, uint8_t *eom, uint8_t *src,
char *dst, size_t dstsiz); char *dst, size_t dstsiz);
#endif /* NS_NAME_H_ */ #endif /* NS_NAME_H_ */

@ -57,9 +57,9 @@
static void setsection_vlmcsd(ns_msg_vlmcsd *msg, ns_sect_vlmcsd sect); static void setsection_vlmcsd(ns_msg_vlmcsd *msg, ns_sect_vlmcsd sect);
static int dn_skipname_vlmcsd(const unsigned char *s, const unsigned char *end) static int dn_skipname_vlmcsd(unsigned char *s, unsigned char *end)
{ {
const unsigned char *p; unsigned char *p;
for (p=s; p<end; p++) for (p=s; p<end; p++)
if (!*p) return p-s+1; if (!*p) return p-s+1;
else if (*p>=192) else if (*p>=192)
@ -69,8 +69,8 @@ static int dn_skipname_vlmcsd(const unsigned char *s, const unsigned char *end)
} }
static int static int
ns_skiprr_vlmcsd(const uint8_t *ptr, const uint8_t *eom, ns_sect_vlmcsd section, int count) { ns_skiprr_vlmcsd(uint8_t *ptr, uint8_t *eom, ns_sect_vlmcsd section, int count) {
const uint8_t *optr = ptr; uint8_t *optr = ptr;
for ((void)NULL; count > 0; count--) { for ((void)NULL; count > 0; count--) {
int b, rdlength; int b, rdlength;
@ -93,8 +93,8 @@ ns_skiprr_vlmcsd(const uint8_t *ptr, const uint8_t *eom, ns_sect_vlmcsd section,
} }
int int
ns_initparse_vlmcsd(const uint8_t *msg, int msglen, ns_msg_vlmcsd *handle) { ns_initparse_vlmcsd(uint8_t *msg, int msglen, ns_msg_vlmcsd *handle) {
const uint8_t *eom = msg + msglen; uint8_t *eom = msg + msglen;
int i; int i;
memset(handle, 0x5e, sizeof *handle); memset(handle, 0x5e, sizeof *handle);

@ -46,12 +46,12 @@ typedef enum __ns_sect_vlmcsd {
} ns_sect_vlmcsd; } ns_sect_vlmcsd;
typedef struct __ns_msg_vlmcsd { typedef struct __ns_msg_vlmcsd {
const uint8_t *_msg, *_eom; uint8_t *_msg, *_eom;
uint16_t _id, _flags, _counts[ns_s_max_vlmcsd]; uint16_t _id, _flags, _counts[ns_s_max_vlmcsd];
const uint8_t *_sections[ns_s_max_vlmcsd]; uint8_t *_sections[ns_s_max_vlmcsd];
ns_sect_vlmcsd _sect; ns_sect_vlmcsd _sect;
int _rrnum; int _rrnum;
const uint8_t *_msg_ptr; uint8_t *_msg_ptr;
} ns_msg_vlmcsd; } ns_msg_vlmcsd;
@ -61,10 +61,10 @@ typedef struct __ns_rr_vlmcsd {
uint16_t rr_class; uint16_t rr_class;
uint32_t ttl; uint32_t ttl;
uint16_t rdlength; uint16_t rdlength;
const uint8_t * rdata; uint8_t * rdata;
} ns_rr_vlmcsd; } ns_rr_vlmcsd;
int ns_initparse_vlmcsd(const uint8_t *msg, int msglen, ns_msg_vlmcsd *handle); int ns_initparse_vlmcsd(uint8_t *msg, int msglen, ns_msg_vlmcsd *handle);
int ns_parserr_vlmcsd(ns_msg_vlmcsd *handle, ns_sect_vlmcsd section, int rrnum, ns_rr_vlmcsd *rr); int ns_parserr_vlmcsd(ns_msg_vlmcsd *handle, ns_sect_vlmcsd section, int rrnum, ns_rr_vlmcsd *rr);

@ -180,7 +180,7 @@ void uuid2StringLE(const GUID *const guid, char *const string)
} }
#if !defined(NO_VERBOSE_LOG) && !defined(NO_LOG) #if !defined(NO_VERBOSE_LOG) && !defined(NO_LOG)
void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p) void logRequestVerbose(REQUEST* Request, const PRINTFUNC p)
{ {
char guidBuffer[GUID_STRING_LENGTH + 1]; char guidBuffer[GUID_STRING_LENGTH + 1];
char WorkstationBuffer[3 * WORKSTATION_NAME_BUFFER]; char WorkstationBuffer[3 * WORKSTATION_NAME_BUFFER];
@ -222,7 +222,7 @@ void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p)
p("N count policy (minimum clients): %u\n", (uint32_t)LE32(Request->N_Policy)); p("N count policy (minimum clients): %u\n", (uint32_t)LE32(Request->N_Policy));
} }
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, const RESPONSE *const response, const PRINTFUNC p) void logResponseVerbose(const char *const ePID, const BYTE *const hwid, RESPONSE* response, const PRINTFUNC p)
{ {
char guidBuffer[GUID_STRING_LENGTH + 1]; char guidBuffer[GUID_STRING_LENGTH + 1];

@ -14,8 +14,8 @@ typedef int (*PRINTFUNC)(const char *const fmt, ...);
int printerrorf(const char *const fmt, ...); int printerrorf(const char *const fmt, ...);
int errorout(const char* fmt, ...); int errorout(const char* fmt, ...);
void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p); void logRequestVerbose(REQUEST* Request, const PRINTFUNC p);
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, const RESPONSE *const response, const PRINTFUNC p); void logResponseVerbose(const char *const ePID, const BYTE *const hwid, RESPONSE* response, const PRINTFUNC p);
#ifndef NO_VERSION_INFORMATION #ifndef NO_VERSION_INFORMATION
void printPlatform(); void printPlatform();

@ -325,7 +325,7 @@ static int rpcRequest(const RPC_REQUEST64 *const Request, RPC_RESPONSE64 *const
# endif // !SIMPLE_RPC # endif // !SIMPLE_RPC
pRpcReturnCode = ((BYTE*)&Response->Ndr) + len; pRpcReturnCode = ((BYTE*)&Response->Ndr) + len;
UA32(pRpcReturnCode) = ResponseSize < 0 ? LE32(ResponseSize) : 0; PUT_UA32LE(pRpcReturnCode, ResponseSize < 0 ? ResponseSize : 0);
len += sizeof(DWORD); len += sizeof(DWORD);
// Pad zeros to 32-bit align (seems not neccassary but Windows RPC does it this way) // Pad zeros to 32-bit align (seems not neccassary but Windows RPC does it this way)
@ -371,7 +371,7 @@ static void CheckRpcBindRequest(const RPC_BIND_REQUEST *const Request, const uns
if (ctxItem->InterfaceVerMajor != LE16(1) || ctxItem->InterfaceVerMinor != 0) if (ctxItem->InterfaceVerMajor != LE16(1) || ctxItem->InterfaceVerMinor != 0)
logger("Warning: Interface version is %u.%u but should be 1.0.\n", logger("Warning: Interface version is %u.%u but should be 1.0.\n",
(unsigned int)LE16(ctxItem->InterfaceVerMajor), (unsigned int)LE16(ctxItem->InterfaceVerMajor),
(unsigned int)LE16(ctxItem->InterfaceVerMinor) (unsigned int)LE16(ctxItem->InterfaceVerMinor)
); );
@ -494,7 +494,7 @@ static int rpcBind(const RPC_BIND_REQUEST *const Request, RPC_BIND_RESPONSE* Res
for (i = 0; i < numCtxItems; i++) for (i = 0; i < numCtxItems; i++)
{ {
struct CtxResults* result = Response->Results+i; struct CtxResults* result = Response->Results + i;
const GUID* ctxTransferSyntax = &Request->CtxItems[i].TransferSyntax; const GUID* ctxTransferSyntax = &Request->CtxItems[i].TransferSyntax;
# ifndef SIMPLE_RPC # ifndef SIMPLE_RPC
@ -970,7 +970,8 @@ RpcStatus rpcSendRequest(const RpcCtx sock, const BYTE *const kmsRequest, const
} }
pReturnCode = (DWORD*)(*kmsResponse + *responseSize + pad); pReturnCode = (DWORD*)(*kmsResponse + *responseSize + pad);
status = LE32(UA32(pReturnCode)); status = GET_UA32LE(pReturnCode);
//status = LE32(UA32(pReturnCode));
break; break;
} }

@ -55,6 +55,7 @@ typedef struct
const BYTE* HwId; const BYTE* HwId;
#ifndef NO_LOG #ifndef NO_LOG
const char* EpidSource; const char* EpidSource;
uint8_t IsRandom;
#endif // NO_LOG #endif // NO_LOG
} KmsResponseParam_t, *PKmsResponseParam_t; } KmsResponseParam_t, *PKmsResponseParam_t;

@ -52,8 +52,6 @@
#define VLMCS_OPTION_GRAB_INI 1 #define VLMCS_OPTION_GRAB_INI 1
#define VLMCS_OPTION_NO_GRAB_INI 2 #define VLMCS_OPTION_NO_GRAB_INI 2
//#define kmsVersionMinor 0 // Currently constant. May change in future KMS versions
#ifndef IS_LIBRARY #ifndef IS_LIBRARY
// Function Prototypes // Function Prototypes
@ -83,24 +81,19 @@ static int AddressFamily = 0;
static int_fast8_t incompatibleOptions = 0; static int_fast8_t incompatibleOptions = 0;
static const char* fn_ini_client = NULL; static const char* fn_ini_client = NULL;
//static int_fast16_t kmsVersionMinor = 0; //static int_fast16_t kmsVersionMinor = 0;
static const char* ePidGroup[] = { "Windows", "Office2010", "Office2013", "Office2016" }; //static const char* ePidGroup[] = { "Windows", "Office2010", "Office2013", "Office2016" };
static int32_t ActiveProductIndex = 0; static int32_t ActiveProductIndex = 0;
static int32_t NCountPolicy = 0; static int32_t NCountPolicy = 0;
static GUID AppGuid, KmsGuid, SkuGuid; static GUID AppGuid, KmsGuid, SkuGuid;
static uint16_t MinorVersion = 0; static uint16_t MinorVersion = 0;
static uint16_t MajorVersion; static uint16_t MajorVersion;
//#if !MULTI_CALL_BINARY
//uint8_t DefaultKmsData[]={0};
//__pure size_t getDefaultKmsDataSize() { return (size_t)0; }
//#endif // !MULTI_CALL_BINARY
#ifndef NO_DNS #ifndef NO_DNS
static int_fast8_t NoSrvRecordPriority = FALSE; static int_fast8_t NoSrvRecordPriority = FALSE;
#endif // NO_DNS #endif // NO_DNS
typedef char iniFileEpidLines[4][256]; //typedef char iniFileEpidLines[4][256];
typedef struct typedef struct
{ {
@ -943,7 +936,6 @@ static void displayRequestError(RpcCtx *const s, const int status, const int cur
} }
} }
static void newIniBackupFile(const char* const restrict fname) static void newIniBackupFile(const char* const restrict fname)
{ {
FILE *restrict f = fopen(fname, "wb"); FILE *restrict f = fopen(fname, "wb");
@ -965,9 +957,9 @@ static void newIniBackupFile(const char* const restrict fname)
} }
static void updateIniFile(iniFileEpidLines* const restrict lines) static void updateIniFile(char*** restrict lines)
{ {
int_fast8_t lineWritten[vlmcsd_countof(*lines)]; int_fast8_t* lineWritten = (int_fast8_t*)malloc(KmsData->CsvlkCount * sizeof(int_fast8_t));
# if !_MSC_VER # if !_MSC_VER
struct stat statbuf; struct stat statbuf;
# endif # endif
@ -975,7 +967,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
int_fast8_t iniFileExistedBefore = TRUE; int_fast8_t iniFileExistedBefore = TRUE;
unsigned int lineNumber; unsigned int lineNumber;
memset(lineWritten, FALSE, sizeof(lineWritten)); memset(lineWritten, FALSE, KmsData->CsvlkCount * sizeof(int_fast8_t));
char* restrict fn_bak = (char*)vlmcsd_malloc(strlen(fn_ini_client) + 2); char* restrict fn_bak = (char*)vlmcsd_malloc(strlen(fn_ini_client) + 2);
@ -1009,7 +1001,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
vlmcsd_unlink(fn_bak); // Required for Windows. Most Unix systems don't need it. vlmcsd_unlink(fn_bak); // Required for Windows. Most Unix systems don't need it.
if (rename(fn_ini_client, fn_bak)) if (rename(fn_ini_client, fn_bak))
{ {
int error = errno; const int error = errno;
errorout("Fatal: Cannot create %s: %s\n", fn_bak, strerror(error)); errorout("Fatal: Cannot create %s: %s\n", fn_bak, strerror(error));
exit(error); exit(error);
} }
@ -1023,7 +1015,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
if (!in) if (!in)
{ {
int error = errno; const int error = errno;
errorout("Fatal: Cannot open %s: %s\n", fn_bak, strerror(error)); errorout("Fatal: Cannot open %s: %s\n", fn_bak, strerror(error));
exit(error); exit(error);
} }
@ -1032,7 +1024,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
if (!out) if (!out)
{ {
int error = errno; const int error = errno;
errorout("Fatal: Cannot create %s: %s\n", fn_ini_client, strerror(error)); errorout("Fatal: Cannot create %s: %s\n", fn_ini_client, strerror(error));
exit(error); exit(error);
} }
@ -1041,9 +1033,9 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
for (lineNumber = 1; fgets(sourceLine, sizeof(sourceLine), in); lineNumber++) for (lineNumber = 1; fgets(sourceLine, sizeof(sourceLine), in); lineNumber++)
{ {
for (i = 0; i < vlmcsd_countof(*lines); i++) for (i = 0; i < KmsData->CsvlkCount; i++)
{ {
if (*(*lines)[i] && !strncasecmp(sourceLine, (*lines)[i], strlen(ePidGroup[i]))) if (*(*lines)[i] && !strncasecmp(sourceLine, (*lines)[i], strlen(getNextString((KmsData->CsvlkData[i].EPid)))))
{ {
if (lineWritten[i]) break; if (lineWritten[i]) break;
@ -1054,7 +1046,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
} }
} }
if (i >= vlmcsd_countof(*lines)) if (i >= KmsData->CsvlkCount)
{ {
fprintf(out, "%s", sourceLine); fprintf(out, "%s", sourceLine);
} }
@ -1069,7 +1061,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
fclose(in); fclose(in);
for (i = 0; i < vlmcsd_countof(*lines); i++) for (i = 0; i < KmsData->CsvlkCount; i++)
{ {
if (!lineWritten[i] && *(*lines)[i]) if (!lineWritten[i] && *(*lines)[i])
{ {
@ -1080,7 +1072,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
if (fclose(out)) if (fclose(out))
{ {
int error = errno; const int error = errno;
errorout("Fatal: Cannot write to %s: %s\n", fn_ini_client, strerror(error)); errorout("Fatal: Cannot write to %s: %s\n", fn_ini_client, strerror(error));
exit(error); exit(error);
} }
@ -1095,18 +1087,27 @@ static void grabServerData()
{ {
RpcCtx s = INVALID_RPCCTX; RpcCtx s = INVALID_RPCCTX;
WORD MajorVer = 6; WORD MajorVer = 6;
iniFileEpidLines lines; int32_t i;
int32_t j;
char** lines = (char**)vlmcsd_malloc(KmsData->CsvlkCount * sizeof(char*));
GUID* kmsGuids = (GUID*)vlmcsd_malloc(KmsData->CsvlkCount * sizeof(GUID));
static char* Licenses[vlmcsd_countof(lines)] = for (i = 0; i < KmsData->CsvlkCount; i++)
{ {
(char*)"212a64dc-43b1-4d3d-a30c-2fc69d2095c6", // Vista lines[i] = (char*)vlmcsd_malloc(256);
(char*)"e85af946-2e25-47b7-83e1-bebcebeac611", // Office 2010 *lines[i] = 0;
(char*)"e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0", // Office 2013
(char*)"85b5f61b-320b-4be3-814a-b76b2bfafc82", // Office 2016 for (j = 0; j < KmsData->KmsItemCount; j++)
}; {
if (KmsData->KmsItemList[j].EPidIndex == i)
{
kmsGuids[i] = KmsData->KmsItemList[j].Guid;
break;
}
}
}
uint_fast8_t i;
int32_t j;
RESPONSE response; RESPONSE response;
RESPONSE_RESULT result; RESPONSE_RESULT result;
REQUEST request; REQUEST request;
@ -1114,23 +1115,19 @@ static void grabServerData()
int status; int status;
size_t len; size_t len;
for (i = 0; i < vlmcsd_countof(lines); i++) *lines[i] = 0; for (i = 0; i < KmsData->CsvlkCount && MajorVer > 3; i++)
for (i = 0; i < vlmcsd_countof(Licenses) && MajorVer > 3; i++)
{ {
GUID guid; const int32_t kmsIndex = getProductIndex(&kmsGuids[i], KmsData->KmsItemList, KmsData->KmsItemCount, NULL, NULL);
string2UuidLE(Licenses[i], &guid);
int32_t kmsIndex = getProductIndex(&guid, KmsData->KmsItemList, KmsData->KmsItemCount, NULL, NULL);
if (kmsIndex < 0) if (kmsIndex < 0)
{ {
errorout("Warning: KMS GUID %s not in database.\n", Licenses[i]); errorout("Warning: KMS GUID not in database.\n");
continue; continue;
} }
ActiveProductIndex = ~0; ActiveProductIndex = ~0;
for (j = KmsData->SkuItemCount; j >= 0; j--) for (j = KmsData->SkuItemCount - 1; j >= 0; j--)
{ {
if (KmsData->SkuItemList[j].KmsIndex == kmsIndex) if (KmsData->SkuItemList[j].KmsIndex == kmsIndex)
{ {
@ -1141,11 +1138,11 @@ static void grabServerData()
if (ActiveProductIndex == ~0) if (ActiveProductIndex == ~0)
{ {
errorout("Warning: KMS GUID %s not in database.\n", Licenses[i]); errorout("Warning: KMS GUID not in database.\n");
continue; continue;
} }
int32_t appIndex = KmsData->SkuItemList[ActiveProductIndex].AppIndex; const int32_t appIndex = KmsData->SkuItemList[ActiveProductIndex].AppIndex;
NCountPolicy = (uint32_t)KmsData->SkuItemList[ActiveProductIndex].NCountPolicy; NCountPolicy = (uint32_t)KmsData->SkuItemList[ActiveProductIndex].NCountPolicy;
memcpy(&SkuGuid, &KmsData->SkuItemList[ActiveProductIndex].Guid, sizeof(GUID)); memcpy(&SkuGuid, &KmsData->SkuItemList[ActiveProductIndex].Guid, sizeof(GUID));
@ -1154,7 +1151,7 @@ static void grabServerData()
MajorVersion = (uint16_t)MajorVer; MajorVersion = (uint16_t)MajorVer;
status = sendRequest(&s, &request, &response, hwid, &result); status = sendRequest(&s, &request, &response, hwid, &result);
printf("%-11s", ePidGroup[i]); printf("%-11s", getNextString(KmsData->CsvlkData[i].EPid));
if (status) if (status)
{ {
@ -1171,7 +1168,7 @@ static void grabServerData()
continue; continue;
} }
printf("%i of %i", (int)(i + 7 - MajorVer), (int)(10 - MajorVer)); printf("%i of %i", (int)(i + 7 - MajorVer), (int)(KmsData->CsvlkCount + 6 - MajorVer));
displayResponse(result, &request, &response, hwid); displayResponse(result, &request, &response, hwid);
char ePID[3 * PID_BUFFER_SIZE]; char ePID[3 * PID_BUFFER_SIZE];
@ -1181,16 +1178,16 @@ static void grabServerData()
memset(ePID + 3 * PID_BUFFER_SIZE - 3, 0, 3); memset(ePID + 3 * PID_BUFFER_SIZE - 3, 0, 3);
} }
vlmcsd_snprintf(lines[i], sizeof(lines[0]), "%s = %s", ePidGroup[i], ePID); vlmcsd_snprintf(lines[i], 255 - strlen(lines[i]), "%s = %s", getNextString(KmsData->CsvlkData[i].EPid), ePID);
if (response.MajorVer > 5) if (response.MajorVer > 5)
{ {
len = strlen(lines[i]); len = strlen(lines[i]);
vlmcsd_snprintf(lines[i] + len, sizeof(lines[0]) - len, " / %02X %02X %02X %02X %02X %02X %02X %02X", hwid[0], hwid[1], hwid[2], hwid[3], hwid[4], hwid[5], hwid[6], hwid[7]); vlmcsd_snprintf(lines[i] + len, 255 - len, " / %02X %02X %02X %02X %02X %02X %02X %02X", hwid[0], hwid[1], hwid[2], hwid[3], hwid[4], hwid[5], hwid[6], hwid[7]);
} }
len = strlen(lines[i]); len = strlen(lines[i]);
vlmcsd_snprintf(lines[i] + len, sizeof(lines[0]) - len, "\n"); vlmcsd_snprintf(lines[i] + len, 255 - len, "\n");
} }
@ -1201,7 +1198,7 @@ static void grabServerData()
else else
{ {
printf("\n"); printf("\n");
for (i = 0; i < vlmcsd_countof(lines); i++) printf("%s", lines[i]); for (i = 0; i < KmsData->CsvlkCount; i++) printf("%s", lines[i]);
} }
} }
@ -1212,10 +1209,10 @@ int client_main(int argc, CARGV argv)
// Windows Sockets must be initialized // Windows Sockets must be initialized
WSADATA wsadata; WSADATA wsaData;
int error; int error;
if ((error = WSAStartup(0x0202, &wsadata))) if ((error = WSAStartup(0x0202, &wsaData)))
{ {
errorout("Fatal: Could not initialize Windows sockets (Error: %d).\n", error); errorout("Fatal: Could not initialize Windows sockets (Error: %d).\n", error);
return error; return error;
@ -1245,7 +1242,7 @@ int client_main(int argc, CARGV argv)
else else
useDefaultHost = TRUE; useDefaultHost = TRUE;
int hostportarg = optind; const int hostportarg = optind;
if (optind < argc - 1) if (optind < argc - 1)
{ {

@ -93,21 +93,23 @@ static uint_fast8_t maxsockets = 0;
#ifdef _NTSERVICE #ifdef _NTSERVICE
static int_fast8_t installService = 0; static int_fast8_t installService = 0;
static const char *restrict ServiceUser = NULL; static const char* restrict ServiceUser = NULL;
static const char *restrict ServicePassword = ""; static const char* restrict ServicePassword = "";
#endif #endif
#ifndef NO_PID_FILE #ifndef NO_PID_FILE
static const char *fn_pid = NULL; static const char* fn_pid = NULL;
#endif #endif
#ifndef NO_INI_FILE #if !defined(NO_INI_FILE) || !defined(NO_CL_PIDS)
#ifndef NO_INI_FILE
#ifdef INI_FILE #ifdef INI_FILE
static const char *fn_ini = INI_FILE; static const char* fn_ini = INI_FILE;
#else // !INI_FILE #else // !INI_FILE
static const char *fn_ini = NULL; static const char* fn_ini = NULL;
#endif // !INI_FILE #endif // !INI_FILE
#endif // NO_INI_FILE
#ifndef NO_TAP #ifndef NO_TAP
char* tapArgument = NULL; char* tapArgument = NULL;
@ -203,12 +205,12 @@ static int shmid = -1;
#ifndef NO_USER_SWITCH #ifndef NO_USER_SWITCH
#ifndef _WIN32 #ifndef _WIN32
static const char *uname = NULL, *gname = NULL; static const char* uname = NULL, * gname = NULL;
static gid_t gid = INVALID_GID; static gid_t gid = INVALID_GID;
static uid_t uid = INVALID_UID; static uid_t uid = INVALID_UID;
// Get Numeric id of user/group // Get Numeric id of user/group
static char GetNumericId(gid_t *restrict id, const char *const c) static char GetNumericId(gid_t* restrict id, const char* const c)
{ {
char* endptr; char* endptr;
gid_t temp; gid_t temp;
@ -224,7 +226,7 @@ static char GetNumericId(gid_t *restrict id, const char *const c)
// Get group id from option argument // Get group id from option argument
static char GetGid() static char GetGid()
{ {
struct group *g; struct group* g;
if ((g = getgrnam(optarg))) if ((g = getgrnam(optarg)))
gid = g->gr_gid; gid = g->gr_gid;
@ -238,7 +240,7 @@ static char GetGid()
// Get user id from option argument // Get user id from option argument
static char GetUid() static char GetUid()
{ {
struct passwd *u; struct passwd* u;
////PORTABILITY: Assumes uid_t and gid_t are of same size (shouldn't be a problem) ////PORTABILITY: Assumes uid_t and gid_t are of same size (shouldn't be a problem)
if ((u = getpwnam(optarg))) if ((u = getpwnam(optarg)))
@ -380,9 +382,9 @@ static __noreturn void usage()
#ifndef NO_CUSTOM_INTERVALS #ifndef NO_CUSTOM_INTERVALS
#ifndef NO_INI_FILE #if !defined(NO_INI_FILE)
__pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char *const restrict argument) __pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char* const restrict argument)
{ {
const DWORD val = timeSpanString2Minutes(argument); const DWORD val = timeSpanString2Minutes(argument);
@ -396,10 +398,10 @@ __pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char *const restr
return TRUE; return TRUE;
} }
#endif // NO_INI_FILE #endif // !defined(NO_INI_FILE)
__pure static DWORD getTimeSpanFromCommandLine(const char *const restrict arg, const char optchar) __pure static DWORD getTimeSpanFromCommandLine(const char* const restrict arg, const char optchar)
{ {
const DWORD val = timeSpanString2Minutes(arg); const DWORD val = timeSpanString2Minutes(arg);
@ -424,13 +426,13 @@ static __pure int isControlCharOrSlash(const char c)
} }
static void iniFileLineNextWord(const char **s) static void iniFileLineNextWord(const char** s)
{ {
while (**s && isspace((int)**s)) (*s)++; while (**s && isspace((int)**s)) (*s)++;
} }
static BOOL setHwIdFromIniFileLine(const char **s, const uint32_t index, const uint8_t overwrite) static BOOL setHwIdFromIniFileLine(const char** s, const uint32_t index, const uint8_t overwrite)
{ {
iniFileLineNextWord(s); iniFileLineNextWord(s);
@ -438,8 +440,8 @@ static BOOL setHwIdFromIniFileLine(const char **s, const uint32_t index, const u
{ {
if (!overwrite && KmsResponseParameters[index].HwId) return TRUE; if (!overwrite && KmsResponseParameters[index].HwId) return TRUE;
BYTE* HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6 *)0)->HwId)); BYTE* HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6*)0)->HwId));
hex2bin(HwId, *s + 1, sizeof(((RESPONSE_V6 *)0)->HwId)); hex2bin(HwId, *s + 1, sizeof(((RESPONSE_V6*)0)->HwId));
KmsResponseParameters[index].HwId = HwId; KmsResponseParameters[index].HwId = HwId;
} }
@ -447,10 +449,10 @@ static BOOL setHwIdFromIniFileLine(const char **s, const uint32_t index, const u
} }
static BOOL setEpidFromIniFileLine(const char **s, const uint32_t index, const char *ePidSource, const uint8_t overwrite) static BOOL setEpidFromIniFileLine(const char** s, const uint32_t index, const char* ePidSource, const uint8_t overwrite)
{ {
iniFileLineNextWord(s); iniFileLineNextWord(s);
const char *savedPosition = *s; const char* savedPosition = *s;
uint_fast16_t i; uint_fast16_t i;
for (i = 0; !isControlCharOrSlash(**s); i++) for (i = 0; !isControlCharOrSlash(**s); i++)
@ -478,34 +480,16 @@ static BOOL setEpidFromIniFileLine(const char **s, const uint32_t index, const c
return TRUE; return TRUE;
} }
#endif // !defined(NO_INI_FILE) || !defined (NO_CL_PIDS)
#ifndef NO_INI_FILE
static void ignoreIniFileParameter(uint_fast8_t iniFileParameterId)
{
uint_fast8_t i;
for (i = 0; i < vlmcsd_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 #ifndef NO_INI_FILE
static BOOL getIniFileArgumentBool(int_fast8_t *result, const char *const argument) static BOOL getIniFileArgumentBool(int_fast8_t* result, const char* const argument)
{ {
IniFileErrorMessage = "Argument must be true/on/yes/1 or false/off/no/0"; IniFileErrorMessage = "Argument must be true/on/yes/1 or false/off/no/0";
return getArgumentBool(result, argument); return getArgumentBool(result, argument);
} }
static BOOL getIniFileArgumentInt(unsigned int *result, const char *const argument, const unsigned int min, const unsigned int max) static BOOL getIniFileArgumentInt(unsigned int* result, const char* const argument, const unsigned int min, const unsigned int max)
{ {
unsigned int tempResult; unsigned int tempResult;
@ -521,7 +505,7 @@ static BOOL getIniFileArgumentInt(unsigned int *result, const char *const argume
} }
static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg) static BOOL setIniFileParameter(uint_fast8_t id, const char* const iniarg)
{ {
unsigned int result; unsigned int result;
BOOL success = TRUE; BOOL success = TRUE;
@ -539,7 +523,7 @@ static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
case INI_PARAM_GID: case INI_PARAM_GID:
{ {
struct group *g; struct group* g;
IniFileErrorMessage = "Invalid group id or name"; IniFileErrorMessage = "Invalid group id or name";
if (!(gname = vlmcsd_strdup(iniarg))) return FALSE; if (!(gname = vlmcsd_strdup(iniarg))) return FALSE;
@ -552,7 +536,7 @@ static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
case INI_PARAM_UID: case INI_PARAM_UID:
{ {
struct passwd *p; struct passwd* p;
IniFileErrorMessage = "Invalid user id or name"; IniFileErrorMessage = "Invalid user id or name";
if (!(uname = vlmcsd_strdup(iniarg))) return FALSE; if (!(uname = vlmcsd_strdup(iniarg))) return FALSE;
@ -749,9 +733,11 @@ static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
return success; return success;
} }
#endif // !NO_INI_FILE
static BOOL getIniFileArgument(const char **s) static BOOL getIniFileArgument(const char** s)
{ {
while (!isspace((int)**s) && **s != '=' && **s) (*s)++; while (!isspace((int)**s) && **s != '=' && **s) (*s)++;
iniFileLineNextWord(s); iniFileLineNextWord(s);
@ -773,18 +759,14 @@ static BOOL getIniFileArgument(const char **s)
return TRUE; return TRUE;
} }
static char* GetNextString(char* s)
{
return s + strlen(s) + 1;
}
static int8_t GetCsvlkIndexFromName(const char *s) static int8_t GetCsvlkIndexFromName(const char* s)
{ {
int8_t i; int8_t i;
for (i = 0; i < KmsData->CsvlkCount; i++) for (i = 0; i < KmsData->CsvlkCount; i++)
{ {
const char *csvlkName = GetNextString(KmsData->CsvlkData[i].EPid); const char* csvlkName = getNextString(KmsData->CsvlkData[i].EPid);
if (!strncasecmp(csvlkName, s, strlen(csvlkName))) if (!strncasecmp(csvlkName, s, strlen(csvlkName)))
{ {
@ -795,7 +777,7 @@ static int8_t GetCsvlkIndexFromName(const char *s)
return -1; return -1;
} }
static BOOL handleIniFileEpidParameter(const char *s, uint8_t allowIniFileDirectives, const char *ePidSource) static BOOL handleIniFileEpidParameter(const char* s, uint8_t allowIniFileDirectives, const char* ePidSource)
{ {
int_fast16_t i; int_fast16_t i;
@ -824,7 +806,26 @@ static BOOL handleIniFileEpidParameter(const char *s, uint8_t allowIniFileDirect
return FALSE; return FALSE;
} }
static BOOL handleIniFileParameter(const char *s) #endif // !defined(NO_INI_FILE) || !defined (NO_CL_PIDS)
#ifndef NO_INI_FILE
static void ignoreIniFileParameter(uint_fast8_t iniFileParameterId)
{
uint_fast8_t i;
for (i = 0; i < vlmcsd_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 handleIniFileParameter(const char* s)
{ {
uint_fast8_t i; uint_fast8_t i;
@ -843,7 +844,7 @@ static BOOL handleIniFileParameter(const char *s)
#if !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC) #if !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
static BOOL setupListeningSocketsFromIniFile(const char *s) static BOOL setupListeningSocketsFromIniFile(const char* s)
{ {
if (!maxsockets) return TRUE; if (!maxsockets) return TRUE;
if (strncasecmp("Listen", s, 6)) return TRUE; if (strncasecmp("Listen", s, 6)) return TRUE;
@ -859,25 +860,30 @@ static BOOL setupListeningSocketsFromIniFile(const char *s)
static BOOL readIniFile(const uint_fast8_t pass) static BOOL readIniFile(const uint_fast8_t pass)
{ {
char line[256]; char line[256];
const char *s; const char* s;
unsigned int lineNumber; unsigned int lineNumber;
uint_fast8_t lineParseError; uint_fast8_t lineParseError;
FILE *restrict f; FILE* restrict f;
BOOL result = TRUE; BOOL result = TRUE;
if (pass == INI_FILE_PASS_2 && KmsData->MinorVer < 6)
{
return TRUE;
}
IniFileErrorBuffer = (char*)vlmcsd_malloc(INIFILE_ERROR_BUFFERSIZE); IniFileErrorBuffer = (char*)vlmcsd_malloc(INIFILE_ERROR_BUFFERSIZE);
if (!((f = fopen(fn_ini, "r")))) return FALSE; if (!((f = fopen(fn_ini, "r")))) return FALSE;
for (lineNumber = 1; (s = fgets(line, sizeof(line), f)); lineNumber++) for (lineNumber = 1; (s = fgets(line, sizeof(line), f)); lineNumber++)
{ {
line[strlen(line) - 1] = 0; size_t i;
for (i = strlen(line); i > 0; i--)
{
if (line[i - 1] != 0xd && line[i - 1] != 0xa)
{
break;
}
}
line[i] = 0;
iniFileLineNextWord(&s); iniFileLineNextWord(&s);
if (*s == ';' || *s == '#' || !*s) continue; if (*s == ';' || *s == '#' || !*s) continue;
@ -965,7 +971,7 @@ __noreturn static void HangupHandler(const int signal_unused)
} }
argv_out[argc_in] = argv_out[argc_in + 1] = NULL; argv_out[argc_in] = argv_out[argc_in + 1] = NULL;
if (daemonize_protection) argv_out[argc_in] = (char*) "-Z"; if (daemonize_protection) argv_out[argc_in] = (char*)"-Z";
exec_self((char**)argv_out); exec_self((char**)argv_out);
int error = errno; int error = errno;
@ -1084,7 +1090,7 @@ static DWORD daemonizeAndSetSignalAction()
// Workaround for Cygwin fork problem (only affects cygwin processes that are Windows services) // Workaround for Cygwin fork problem (only affects cygwin processes that are Windows services)
// Best is to compile for Cygwin with threads. fork() is slow and unreliable on Cygwin // 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) || !defined(NO_EXTERNAL_DATA) #if !defined(NO_INI_FILE) || !defined(NO_LOG) || !defined(NO_CL_PIDS) || !defined(NO_EXTERNAL_DATA)
__pure static char* getCommandLineArg(char *const restrict arg) __pure static char* getCommandLineArg(char* const restrict arg)
{ {
# if !__CYGWIN__ || defined(USE_THREADS) || defined(NO_SOCKETS) # if !__CYGWIN__ || defined(USE_THREADS) || defined(NO_SOCKETS)
return arg; return arg;
@ -1325,14 +1331,6 @@ static void parseGeneralArguments() {
case 'H': case 'H':
HostBuild = (uint16_t)getOptionArgumentInt((char)o, 0, 0xffff); HostBuild = (uint16_t)getOptionArgumentInt((char)o, 0, 0xffff);
ignoreIniFileParameter(INI_PARAM_HOST_BUILD); ignoreIniFileParameter(INI_PARAM_HOST_BUILD);
# ifdef _PEDANTIC
if (!IsValidHostBuild(HostBuild))
{
printerrorf("Warning: %u is not a known released Windows Server build >= 2008.\n");
}
# endif // _PEDANTIC
break; break;
# endif // NO_RANDOM_PID # endif // NO_RANDOM_PID
@ -1437,7 +1435,7 @@ static void writePidFile()
if (fn_pid && !InetdMode) if (fn_pid && !InetdMode)
{ {
FILE *file = fopen(fn_pid, "w"); FILE* file = fopen(fn_pid, "w");
if (file) if (file)
{ {
@ -1455,8 +1453,8 @@ static void writePidFile()
logger("Warning: Cannot write pid file '%s'. %s.\n", fn_pid, strerror(errno)); logger("Warning: Cannot write pid file '%s'. %s.\n", fn_pid, strerror(errno));
} }
# endif // NO_LOG # endif // NO_LOG
}
} }
}
#else #else
#define writePidFile() #define writePidFile()
#endif // !defined(NO_PID_FILE) #endif // !defined(NO_PID_FILE)
@ -1563,8 +1561,8 @@ static void allocateSemaphore(void)
{ {
printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno)); printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno));
MaxTasks = SEM_VALUE_MAX; MaxTasks = SEM_VALUE_MAX;
} }
} }
# endif // THREADS or CYGWIN # endif // THREADS or CYGWIN
@ -1577,7 +1575,7 @@ static void allocateSemaphore(void)
} }
# endif // _WIN32 # endif // _WIN32
} }
} }
#endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__ #endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
@ -1656,7 +1654,7 @@ int setupListeningSockets()
if (haveIPv6Stack) addListeningSocket("::"); if (haveIPv6Stack) addListeningSocket("::");
if (haveIPv4Stack) addListeningSocket("0.0.0.0"); if (haveIPv4Stack) addListeningSocket("0.0.0.0");
# endif // !HAVE_GETIFADDR # endif // !HAVE_GETIFADDR
} }
if (!numsockets) if (!numsockets)
{ {
@ -1751,7 +1749,7 @@ int newmain()
# ifndef NO_LOG # ifndef NO_LOG
logstdout = 0; logstdout = 0;
# endif // !NO_LOG # endif // !NO_LOG
} }
# endif // !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC) # endif // !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
@ -1776,9 +1774,9 @@ int newmain()
!IsNDR64Defined !IsNDR64Defined
) )
{ {
UseServerRpcNDR64 = !!KmsData->Flags & KMS_OPTIONS_USENDR64; UseServerRpcNDR64 = !!(KmsData->Flags & KMS_OPTIONS_USENDR64);
# ifndef NO_RANDOM_EPID # ifndef NO_RANDOM_EPID
if (HostBuild&&RandomizationLevel) if (HostBuild && RandomizationLevel)
{ {
UseServerRpcNDR64 = HostBuild > 7601; UseServerRpcNDR64 = HostBuild > 7601;
} }
@ -1786,13 +1784,6 @@ int newmain()
} }
# endif // !defined(USE_MSRPC) && !defined(SIMPLE_RPC) # endif // !defined(USE_MSRPC) && !defined(SIMPLE_RPC)
# if !defined(NO_INI_FILE) || !defined(NO_CL_PIDS)
if (KmsData->MinorVer < 6)
{
printerrorf("Warning: Need database version 1.6 or greater to set custom ePids\n");
}
# endif // !defined(NO_INI_FILE) || !defined(NO_CL_PIDS)
# if !defined(NO_RANDOM_EPID) || !defined(NO_CL_PIDS) || !defined(NO_INI_FILE) # if !defined(NO_RANDOM_EPID) || !defined(NO_CL_PIDS) || !defined(NO_INI_FILE)
KmsResponseParameters = (KmsResponseParam_t*)vlmcsd_malloc(sizeof(KmsResponseParam_t) * KmsData->CsvlkCount); KmsResponseParameters = (KmsResponseParam_t*)vlmcsd_malloc(sizeof(KmsResponseParam_t) * KmsData->CsvlkCount);
memset(KmsResponseParameters, 0, sizeof(KmsResponseParam_t) * KmsData->CsvlkCount); memset(KmsResponseParameters, 0, sizeof(KmsResponseParam_t) * KmsData->CsvlkCount);
@ -1805,7 +1796,7 @@ int newmain()
for (opterr = 0; (o = getopt(global_argc, (char* const*)global_argv, (const char*)optstring)) > 0; ) switch (o) for (opterr = 0; (o = getopt(global_argc, (char* const*)global_argv, (const char*)optstring)) > 0; ) switch (o)
{ {
case 'a': case 'a':
if (KmsData->MinorVer < 6 || !handleIniFileEpidParameter(optarg, FALSE, "command line")) if (!handleIniFileEpidParameter(optarg, FALSE, "command line"))
{ {
usage(); usage();
} }
@ -1892,7 +1883,7 @@ int newmain()
{ {
printerrorf("Fatal: %s for %s failed: %s\n", "setuid", uname, strerror(errno)); printerrorf("Fatal: %s for %s failed: %s\n", "setuid", uname, strerror(errno));
return errno; return errno;
} }
# ifndef NO_SIGHUP # ifndef NO_SIGHUP
} }
# endif // NO_SIGHUP # endif // NO_SIGHUP
@ -1905,6 +1896,22 @@ int newmain()
// the lifetime of the process. So we generate them now // the lifetime of the process. So we generate them now
# ifndef NO_RANDOM_EPID # ifndef NO_RANDOM_EPID
if (RandomizationLevel == 1) randomPidInit(); if (RandomizationLevel == 1) randomPidInit();
# if !defined(NO_LOG) && !defined(NO_VERBOSE_LOG)
if (logverbose)
{
int32_t i;
for (i = 0; i < KmsData->CsvlkCount; i++)
{
const CsvlkData_t* const csvlk = KmsData->CsvlkData + i;
const char* csvlkIniName = getNextString(csvlk->EPid);
const char* csvlkFullName = getNextString(csvlkIniName);
csvlkFullName = *csvlkFullName ? csvlkFullName : "unknown";
const char* ePid = KmsResponseParameters[i].Epid ? KmsResponseParameters[i].Epid : RandomizationLevel == 2 ? "" : csvlk->EPid;
logger("Using CSVLK %s (%s) with %s ePID %s\n", csvlkIniName, csvlkFullName, (RandomizationLevel == 1 && KmsResponseParameters[i].IsRandom) || (RandomizationLevel == 2 && !KmsResponseParameters[i].Epid) ? "random" : "fixed", ePid);
}
}
# endif // !defined(NO_LOG) && !defined(NO_VERBOSE_LOG)
# endif # endif
# if !defined(NO_SOCKETS) # if !defined(NO_SOCKETS)
@ -1950,12 +1957,12 @@ int newmain()
#if _MSC_VER && !defined(_DEBUG)&& !MULTI_CALL_BINARY #if _MSC_VER && !defined(_DEBUG)&& !MULTI_CALL_BINARY
int __stdcall WinStartUp(void) int __stdcall WinStartUp(void)
{ {
WCHAR **szArgList; WCHAR** szArgList;
int argc; int argc;
szArgList = CommandLineToArgvW(GetCommandLineW(), &argc); szArgList = CommandLineToArgvW(GetCommandLineW(), &argc);
int i; int i;
char **argv = (char**)vlmcsd_malloc(sizeof(char*)*argc); char** argv = (char**)vlmcsd_malloc(sizeof(char*) * argc);
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {

@ -28,7 +28,7 @@ int server_main(int argc, CARGV argv);
#define SA_NOCLDWAIT 0 #define SA_NOCLDWAIT 0
#endif #endif
#ifndef NO_INI_FILE #if !defined(NO_INI_FILE) || !defined(NO_CL_PIDS)
#define INI_PARAM_RANDOMIZATION_LEVEL 1 #define INI_PARAM_RANDOMIZATION_LEVEL 1
#define INI_PARAM_LCID 2 #define INI_PARAM_LCID 2
#define INI_PARAM_LISTEN 3 #define INI_PARAM_LISTEN 3

@ -42,7 +42,7 @@ static BOOL isAddressAssigned()
BOOL result = FALSE; BOOL result = FALSE;
pIPAddrTable = (PMIB_IPADDRTABLE)vlmcsd_malloc(sizeof(MIB_IPADDRTABLE)); pIPAddrTable = (PMIB_IPADDRTABLE)vlmcsd_malloc(sizeof(MIB_IPADDRTABLE));
DWORD status = GetIpAddrTable(pIPAddrTable, &dwSize, 0); const DWORD status = GetIpAddrTable(pIPAddrTable, &dwSize, 0);
free(pIPAddrTable); free(pIPAddrTable);
if (status != ERROR_INSUFFICIENT_BUFFER) return FALSE; if (status != ERROR_INSUFFICIENT_BUFFER) return FALSE;
@ -74,16 +74,16 @@ static BOOL isAddressAssigned()
static void parseTapArgument(char* argument) static void parseTapArgument(char* argument)
{ {
char* equalsignPosition = strchr(argument, (int)'='); char* equalSignPosition = strchr(argument, (int)'=');
char* slashPosition = strchr(argument, (int)'/'); char* slashPosition = strchr(argument, (int)'/');
char* colonPosition = strchr(argument, (int)':'); char* colonPosition = strchr(argument, (int)':');
szTapName = argument; szTapName = argument;
if (equalsignPosition) if (equalSignPosition)
{ {
*equalsignPosition = 0; *equalSignPosition = 0;
szIpAddress = equalsignPosition + 1; szIpAddress = equalSignPosition + 1;
} }
if (slashPosition) if (slashPosition)
@ -166,10 +166,10 @@ static HANDLE OpenTapHandle()
WinErrorExit(regResult); WinErrorExit(regResult);
} }
char subkeyName[TAP_REGISTRY_DATA_SIZE]; char subKeyName[TAP_REGISTRY_DATA_SIZE];
DWORD i, subKeySize = sizeof(subkeyName); DWORD i, subKeySize = sizeof(subKeyName);
for (i = 0; (regResult = RegEnumKeyEx(regAdapterKey, i, subkeyName, &subKeySize, NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS; i++) for (i = 0; (regResult = RegEnumKeyEx(regAdapterKey, i, subKeyName, &subKeySize, NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS; i++)
{ {
HKEY regSubKey; HKEY regSubKey;
DWORD type, regDataSize; DWORD type, regDataSize;
@ -177,7 +177,7 @@ static HANDLE OpenTapHandle()
if (regResult) WinErrorExit(regResult); if (regResult) WinErrorExit(regResult);
if ((regResult = RegOpenKeyEx(regAdapterKey, subkeyName, 0, KEY_READ | KEY_WOW64_64KEY, &regSubKey)) == ERROR_SUCCESS) if ((regResult = RegOpenKeyEx(regAdapterKey, subKeyName, 0, KEY_READ | KEY_WOW64_64KEY, &regSubKey)) == ERROR_SUCCESS)
{ {
regDataSize = sizeof(regData); regDataSize = sizeof(regData);
@ -201,8 +201,8 @@ static HANDLE OpenTapHandle()
char connectionKeyName[TAP_REGISTRY_DATA_SIZE]; char connectionKeyName[TAP_REGISTRY_DATA_SIZE];
strncpy(connectionKeyName, NETWORK_CONNECTIONS_KEY "\\", sizeof(connectionKeyName)); strncpy(connectionKeyName, NETWORK_CONNECTIONS_KEY "\\", sizeof(connectionKeyName));
strncat(connectionKeyName, regData, sizeof(connectionKeyName)); strncat(connectionKeyName, regData, sizeof(connectionKeyName) - strlen(connectionKeyName) - 1);
strncat(connectionKeyName, "\\Connection", sizeof(connectionKeyName)); strncat(connectionKeyName, "\\Connection", sizeof(connectionKeyName) - strlen(connectionKeyName) - 1);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, connectionKeyName, 0, KEY_READ | KEY_WOW64_64KEY, &connectionKey) == ERROR_SUCCESS) if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, connectionKeyName, 0, KEY_READ | KEY_WOW64_64KEY, &connectionKey) == ERROR_SUCCESS)
{ {
@ -215,8 +215,8 @@ static HANDLE OpenTapHandle()
{ {
ActiveTapName = vlmcsd_strdup(deviceName); ActiveTapName = vlmcsd_strdup(deviceName);
strncpy(deviceName, USERMODEDEVICEDIR, sizeof(deviceName)); strncpy(deviceName, USERMODEDEVICEDIR, sizeof(deviceName));
strncat(deviceName, regData, sizeof(deviceName)); strncat(deviceName, regData, sizeof(deviceName) - strlen(deviceName) - 1);
strncat(deviceName, strcmp(AdapterClass, "TEAMVIEWERVPN") ? TAP_WIN_SUFFIX : ".dgt", sizeof(deviceName)); strncat(deviceName, strcmp(AdapterClass, "TEAMVIEWERVPN") ? TAP_WIN_SUFFIX : ".dgt", sizeof(deviceName) - strlen(deviceName) - 1);
handle = CreateFile(deviceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL); handle = CreateFile(deviceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
} }
} }
@ -231,7 +231,7 @@ static HANDLE OpenTapHandle()
} }
RegCloseKey(regSubKey); RegCloseKey(regSubKey);
subKeySize = sizeof(subkeyName); subKeySize = sizeof(subKeyName);
if (handle != INVALID_HANDLE_VALUE) break; if (handle != INVALID_HANDLE_VALUE) break;
} }

Loading…
Cancel
Save