mirror of
https://github.com/Wind4/vlmcsd.git
synced 2024-11-24 19:11:04 +08:00
vlmcsd-1113-2020-03-28-Hotbird64
This commit is contained in:
parent
ce1dfa16b2
commit
e599080486
@ -225,9 +225,9 @@ help:
|
||||
@echo " DNS_PARSER=internal Use $(BASE_CLIENT_NAME) internal DNS parsing routines. No effect on MingW (native Windows)."
|
||||
@echo ""
|
||||
@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 " -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 " -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)."
|
||||
|
||||
|
BIN
etc/vlmcsd.kmd
BIN
etc/vlmcsd.kmd
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
.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
|
||||
|
||||
.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"
|
||||
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"
|
||||
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
|
||||
.TH VLMCSD 8 "October 2018" "Hotbird64" "KMS Activation Manual"
|
||||
.TH VLMCSD 8 "February 2019" "Hotbird64" "KMS Activation Manual"
|
||||
.LO 8
|
||||
|
||||
.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.
|
||||
|
||||
.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
|
||||
Office, Project and Visio must be volume license versions.
|
||||
Windows Vista, Windows 7, Office, Project and Visio must be volume license versions.
|
||||
|
||||
.SH FILES
|
||||
.IP "\fBvlmcsd.ini\fR(5)"
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "endian.h"
|
||||
|
||||
#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)
|
||||
|
||||
@ -136,8 +136,12 @@ unsigned short GET_UAA16LE(void *p, unsigned int i)
|
||||
(unsigned short)_p[ 0 ] |
|
||||
(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)
|
||||
{
|
||||
return GET_UAA16BE(&x, 0);
|
||||
|
64
src/endian.h
64
src/endian.h
@ -9,17 +9,17 @@
|
||||
//
|
||||
// Unaligned access
|
||||
//
|
||||
|
||||
#if !defined(NO_COMPILER_UAA)
|
||||
#define UAA16(p, i) (((PACKED16*)p)->val[i])
|
||||
#define UAA32(p, i) (((PACKED32*)p)->val[i])
|
||||
#define UAA64(p, i) (((PACKED64*)p)->val[i])
|
||||
|
||||
#define UA64(p) UAA64(p, 0)
|
||||
#define UA32(p) UAA32(p, 0)
|
||||
#define UA16(p) UAA16(p, 0)
|
||||
#endif
|
||||
|
||||
//
|
||||
//Byteswap: Use compiler support if available
|
||||
//
|
||||
#ifndef NO_COMPILER_UAA
|
||||
#ifdef __has_builtin // Clang supports this
|
||||
|
||||
#if __has_builtin(__builtin_bswap16)
|
||||
@ -56,6 +56,7 @@
|
||||
#endif // GNU C > 4.7
|
||||
#endif // __GNUC__ > 4
|
||||
#endif // __GNUC__
|
||||
#endif // NO_COMPILER_UAA
|
||||
|
||||
//
|
||||
// Byteorder
|
||||
@ -198,6 +199,10 @@
|
||||
#define __BE64(x) BS64(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
|
||||
|
||||
#define __BE16(x) (x)
|
||||
@ -207,8 +212,38 @@
|
||||
#define __BE64(x) (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
|
||||
|
||||
#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_UAA32BE(p, v, i) ( UAA32(p, i) = __BE32(v) )
|
||||
#define PUT_UAA16BE(p, v, i) ( UAA16(p, i) = __BE16(v) )
|
||||
@ -225,12 +260,6 @@
|
||||
#define GET_UAA32LE(p, i) __LE32(UAA32(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)
|
||||
|
||||
@ -260,22 +289,9 @@ extern unsigned long long GET_UAA64LE(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);
|
||||
#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_UA32BE(p, v) PUT_UAA32BE(p, v, 0)
|
||||
|
@ -434,14 +434,14 @@ __pure BOOL getArgumentBool(int_fast8_t *result, const char *const argument)
|
||||
#ifndef NO_EXTERNAL_DATA
|
||||
__noreturn static void dataFileReadError()
|
||||
{
|
||||
int error = errno;
|
||||
const int error = errno;
|
||||
errorout("Fatal: Could not read %s: %s\n", fn_data, strerror(error));
|
||||
exit(error);
|
||||
}
|
||||
|
||||
__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);
|
||||
}
|
||||
#endif // NO_EXTERNAL_DATA
|
||||
@ -526,7 +526,7 @@ static void getDefaultDataFile()
|
||||
getExeName();
|
||||
strncpy(fileName, fn_exe, MAX_PATH);
|
||||
PathRemoveFileSpec(fileName);
|
||||
strncat(fileName, "\\vlmcsd.kmd", MAX_PATH);
|
||||
strncat(fileName, "\\vlmcsd.kmd", MAX_PATH - 11);
|
||||
fn_data = vlmcsd_strdup(fileName);
|
||||
}
|
||||
#else // !_WIN32
|
||||
@ -588,12 +588,12 @@ void loadKmsData()
|
||||
KmsData = (PVlmcsdHeader_t)vlmcsd_malloc(size);
|
||||
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();
|
||||
fclose(file);
|
||||
|
||||
# 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
|
||||
}
|
||||
}
|
||||
@ -610,6 +610,7 @@ void loadKmsData()
|
||||
KmsData->AppItemCount = LE32(KmsData->AppItemCount);
|
||||
KmsData->KmsItemCount = LE32(KmsData->KmsItemCount);
|
||||
KmsData->SkuItemCount = LE32(KmsData->SkuItemCount);
|
||||
KmsData->HostBuildCount = LE32(KmsData->HostBuildCount);
|
||||
|
||||
uint32_t i;
|
||||
|
||||
@ -625,6 +626,7 @@ void loadKmsData()
|
||||
{
|
||||
PCsvlkData_t csvlkData = &KmsData->CsvlkData[i];
|
||||
csvlkData->EPid = (char*)KmsData + LE64(csvlkData->EPidOffset);
|
||||
csvlkData->ReleaseDate = LE64(csvlkData->ReleaseDate);
|
||||
# ifndef UNSAFE_DATA_LOAD
|
||||
if (csvlkData->EPid > (char*)KmsData + size) dataFileFormatError();
|
||||
# endif // UNSAFE_DATA_LOAD
|
||||
@ -636,12 +638,25 @@ void loadKmsData()
|
||||
# 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;
|
||||
|
||||
# ifndef NO_EXTERNAL_DATA
|
||||
if (
|
||||
memcmp(KmsData->Magic, "KMD", sizeof(KmsData->Magic)) ||
|
||||
KmsData->MajorVer != 1
|
||||
KmsData->MajorVer != 2
|
||||
# ifndef UNSAFE_DATA_LOAD
|
||||
||
|
||||
sizeof(VlmcsdHeader_t) + totalItemCount * sizeof(VlmcsdData_t) >= ((uint64_t)size)
|
||||
|
209
src/kms.c
209
src/kms.c
@ -57,16 +57,23 @@ int32_t getProductIndex(const GUID* guid, const PVlmcsdData_t list, const int32_
|
||||
}
|
||||
}
|
||||
|
||||
if (name) *name = "Unknown";
|
||||
if (ePid) *ePid = KmsData->CsvlkData[EPID_INDEX_WINDOWS].EPid;
|
||||
if (name) *name = (char*)"Unknown";
|
||||
if (ePid) *ePid = KmsData->CsvlkData->EPid;
|
||||
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
|
||||
|
||||
|
||||
#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
|
||||
static const uint16_t LcidList[] = {
|
||||
@ -80,13 +87,37 @@ 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
|
||||
};
|
||||
|
||||
uint16_t getPlatformId(uint16_t hostBuild)
|
||||
int32_t getPlatformId(int32_t hostBuild)
|
||||
{
|
||||
if (hostBuild < 9000) return 55041;
|
||||
if (hostBuild <= 9500) return 5426;
|
||||
if (hostBuild <= 10000) return 6401;
|
||||
return 3612;
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i < KmsData->HostBuildCount; i++)
|
||||
{
|
||||
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
|
||||
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;
|
||||
@ -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.
|
||||
// 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);
|
||||
int64_t *filetime = (int64_t*)ts;
|
||||
@ -127,7 +158,7 @@ void getUnixTimeAsFileTime(FILETIME *const ts)
|
||||
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;
|
||||
}
|
||||
@ -255,19 +286,18 @@ static uint8_t getRandomServerType()
|
||||
{
|
||||
# if defined(USE_MSRPC) || defined(SIMPLE_RPC)
|
||||
|
||||
return rand() % vlmcsd_countof(HostBuilds);
|
||||
return rand() % KmsData->HostBuildCount;
|
||||
|
||||
# else // !defined(USE_MSRPC) && !defined(SIMPLE_RPC)
|
||||
if (!UseServerRpcBTFN)
|
||||
while (TRUE)
|
||||
{
|
||||
// This isn't possible at all, e.g. KMS host on XP
|
||||
return rand() % (int)vlmcsd_countof(HostBuilds);
|
||||
const uint32_t buildIndex = rand() % KmsData->HostBuildCount;
|
||||
|
||||
if (!(KmsData->HostBuildList[buildIndex].Flags & UseNdr64) == !UseServerRpcNDR64)
|
||||
{
|
||||
return (uint8_t)buildIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
# endif // !defined(USE_MSRPC) && !defined(SIMPLE_RPC)
|
||||
}
|
||||
|
||||
@ -275,13 +305,13 @@ static uint8_t getRandomServerType()
|
||||
/*
|
||||
* 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];
|
||||
|
||||
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;
|
||||
|
||||
const PCsvlkData_t csvlkData = &KmsData->CsvlkData[index];
|
||||
PCsvlkData_t csvlkData = &KmsData->CsvlkData[index];
|
||||
strcat(szPid, itoc(numberBuffer, csvlkData->GroupId, 5));
|
||||
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, ".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(&maxTime);
|
||||
@ -343,11 +374,33 @@ void randomPidInit()
|
||||
|
||||
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);
|
||||
KmsResponseParameters[i].Epid = (const char*)vlmcsd_strdup(Epid);
|
||||
|
||||
#ifndef NO_LOG
|
||||
KmsResponseParameters[i].EpidSource = "randomized at program start";
|
||||
KmsResponseParameters[i].IsRandom = TRUE;
|
||||
#endif // NO_LOG
|
||||
}
|
||||
}
|
||||
@ -364,7 +417,7 @@ static int32_t getProductIndexFromAllLists(const GUID* guid, char** productName)
|
||||
/*
|
||||
* Logs a Request
|
||||
*/
|
||||
static void logRequest(const REQUEST *const baseRequest)
|
||||
static void logRequest(REQUEST* baseRequest)
|
||||
{
|
||||
#ifndef NO_VERBOSE_LOG
|
||||
if (logverbose)
|
||||
@ -376,7 +429,7 @@ static void logRequest(const REQUEST *const baseRequest)
|
||||
#endif // NO_VERBOSE_LOG
|
||||
|
||||
char *productName;
|
||||
char clientname[64];
|
||||
char clientName[64];
|
||||
|
||||
int32_t index = getProductIndexFromAllLists(&baseRequest->ActID, &productName);
|
||||
if (index < 0) index = getProductIndexFromAllLists(&baseRequest->KMSID, &productName);
|
||||
@ -388,8 +441,8 @@ static void logRequest(const REQUEST *const baseRequest)
|
||||
uuid2StringLE(&baseRequest->ActID, productName);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
#endif // NO_LOG
|
||||
|
||||
@ -493,7 +546,7 @@ static void CheckRequest(const REQUEST *const Request)
|
||||
/*
|
||||
* 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];
|
||||
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
|
||||
*/
|
||||
#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;
|
||||
#ifndef NO_LOG
|
||||
@ -539,7 +592,7 @@ static HRESULT __stdcall CreateResponseBaseCallback(const REQUEST *const baseReq
|
||||
const DWORD minClients = LE32(baseRequest->N_Policy);
|
||||
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
|
||||
|
||||
@ -554,7 +607,7 @@ static HRESULT __stdcall CreateResponseBaseCallback(const REQUEST *const baseReq
|
||||
|
||||
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)
|
||||
{
|
||||
@ -705,21 +758,21 @@ void get16RandomBytes(void* ptr)
|
||||
/*
|
||||
* 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;
|
||||
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;
|
||||
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;
|
||||
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
|
||||
*/
|
||||
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];
|
||||
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));
|
||||
|
||||
// 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.
|
||||
// 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
|
||||
*/
|
||||
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
|
||||
// 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
|
||||
// to a variable sized struct later and requires unaligned access macros.
|
||||
|
||||
RESPONSE_V6* Response = (RESPONSE_V6*)responseBuffer;
|
||||
RESPONSE* baseResponse = &Response->ResponseBase;
|
||||
RESPONSE_V6* response = (RESPONSE_V6*)responseBuffer;
|
||||
RESPONSE* baseResponse = &response->ResponseBase;
|
||||
|
||||
#ifdef _DEBUG
|
||||
// ReSharper disable once CppEntityNeverUsed
|
||||
// ReSharper disable once CppDeclaratorNeverUsed
|
||||
RESPONSE_V6_DEBUG* xxx_unused = (RESPONSE_V6_DEBUG*)responseBuffer;
|
||||
#endif
|
||||
|
||||
static const BYTE DefaultHwid[8] = { HWID };
|
||||
static const BYTE DefaultHwId[8] = { HWID };
|
||||
const int_fast8_t v6 = LE16(request_v6->MajorVer) > 5;
|
||||
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);
|
||||
|
||||
// get random salt and SHA256 it
|
||||
get16RandomBytes(Response->RandomXoredIVs);
|
||||
Sha256(Response->RandomXoredIVs, sizeof(Response->RandomXoredIVs), Response->Hash);
|
||||
get16RandomBytes(response->RandomXoredIVs);
|
||||
Sha256(response->RandomXoredIVs, sizeof(response->RandomXoredIVs), response->Hash);
|
||||
|
||||
if (v6) // V6 specific stuff
|
||||
{
|
||||
// In v6 a random IV is generated
|
||||
Response->Version = request_v6->Version;
|
||||
get16RandomBytes(Response->IV);
|
||||
response->Version = request_v6->Version;
|
||||
get16RandomBytes(response->IV);
|
||||
|
||||
// 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
|
||||
// to XORing non-decrypted request and reponse IVs
|
||||
memcpy(Response->XoredIVs, request_v6->IV, sizeof(Response->XoredIVs));
|
||||
// to XORing non-decrypted request and response IVs
|
||||
memcpy(response->XoredIVs, request_v6->IV, sizeof(response->XoredIVs));
|
||||
}
|
||||
else // V5 specific stuff
|
||||
{
|
||||
// In v5 IVs of request and response must be identical (MS client checks this)
|
||||
// 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
|
||||
XorBlock(request_v6->IV, Response->RandomXoredIVs);
|
||||
XorBlock(request_v6->IV, response->RandomXoredIVs);
|
||||
|
||||
// Get the base response
|
||||
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
|
||||
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
|
||||
size_t encryptSize =
|
||||
V6_PRE_EPID_SIZE
|
||||
- sizeof(Response->Version)
|
||||
- sizeof(response->Version)
|
||||
+ pidSize
|
||||
+ post_epid_size;
|
||||
|
||||
//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
|
||||
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
|
||||
size_t encryptSize = sizeof(request->RequestBase);
|
||||
AesCtx Ctx;
|
||||
int_fast8_t v6 = LE16(request->MajorVer) > 5;
|
||||
AesInitKey(&Ctx, v6 ? AesKeyV6 : AesKeyV5, v6, 16);
|
||||
AesEncryptCbc(&Ctx, request->IV, (BYTE*)(&request->RequestBase), &encryptSize);
|
||||
AesCtx ctx;
|
||||
const int_fast8_t v6 = LE16(request->MajorVer) > 5;
|
||||
AesInitKey(&ctx, v6 ? AesKeyV6 : AesKeyV5, v6, 16);
|
||||
AesEncryptCbc(&ctx, request->IV, (BYTE*)(&request->RequestBase), &encryptSize);
|
||||
|
||||
// Return Proper Request Data
|
||||
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)
|
||||
responseSize -= copySize1;
|
||||
|
||||
AesCtx Ctx;
|
||||
AesCtx ctx;
|
||||
const int_fast8_t v6 = LE16(((RESPONSE_V6*)response)->MajorVer) > 5;
|
||||
|
||||
AesInitKey(&Ctx, v6 ? AesKeyV6 : AesKeyV5, v6, AES_KEY_BYTES);
|
||||
AesDecryptCbc(&Ctx, NULL, response + copySize1, responseSize);
|
||||
AesInitKey(&ctx, v6 ? AesKeyV6 : AesKeyV5, v6, AES_KEY_BYTES);
|
||||
AesDecryptCbc(&ctx, NULL, response + copySize1, responseSize);
|
||||
|
||||
// Check padding
|
||||
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
|
||||
DWORD pidSize = LE32(((RESPONSE_V6*)response)->ResponseBase.PIDSize);
|
||||
const DWORD pidSize = LE32(((RESPONSE_V6*)response)->ResponseBase.PIDSize);
|
||||
|
||||
copySize1 +=
|
||||
V6_UNENCRYPTED_SIZE +
|
||||
@ -1097,9 +1150,9 @@ RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BY
|
||||
REQUEST_V6* request_v6 = (REQUEST_V6*)rawRequest;
|
||||
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 =
|
||||
request_v6->Version == response_v6->ResponseBase.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);
|
||||
|
||||
// Rebuild Random Key and Sha256 Hash
|
||||
BYTE HashVerify[sizeof(response_v6->Hash)];
|
||||
BYTE RandomKey[sizeof(response_v6->RandomXoredIVs)];
|
||||
BYTE hashVerify[sizeof(response_v6->Hash)];
|
||||
BYTE randomKey[sizeof(response_v6->RandomXoredIVs)];
|
||||
|
||||
memcpy(RandomKey, request_v6->IV, sizeof(RandomKey));
|
||||
XorBlock(response_v6->RandomXoredIVs, RandomKey);
|
||||
Sha256(RandomKey, sizeof(RandomKey), HashVerify);
|
||||
memcpy(randomKey, request_v6->IV, sizeof(randomKey));
|
||||
XorBlock(response_v6->RandomXoredIVs, randomKey);
|
||||
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)
|
||||
result.correctResponseSize =
|
||||
|
68
src/kms.h
68
src/kms.h
@ -228,6 +228,14 @@ typedef union
|
||||
|
||||
typedef BYTE hwid_t[8];
|
||||
|
||||
typedef enum
|
||||
{
|
||||
None = 0,
|
||||
UseNdr64 = 1 << 0,
|
||||
UseForEpid = 1 << 1,
|
||||
MayBeServer = 1 << 2,
|
||||
} HostBuildFlag;
|
||||
|
||||
typedef struct CsvlkData
|
||||
{
|
||||
union
|
||||
@ -236,6 +244,7 @@ typedef struct CsvlkData
|
||||
char* EPid;
|
||||
};
|
||||
|
||||
int64_t ReleaseDate;
|
||||
uint32_t GroupId;
|
||||
uint32_t MinKeyId;
|
||||
uint32_t MaxKeyId;
|
||||
@ -280,6 +289,22 @@ typedef struct
|
||||
|
||||
#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
|
||||
{
|
||||
BYTE Magic[4];
|
||||
@ -290,19 +315,21 @@ typedef struct VlmcsdHeader
|
||||
|
||||
union
|
||||
{
|
||||
int32_t Counts[3];
|
||||
int32_t Counts[5];
|
||||
|
||||
struct
|
||||
{
|
||||
int32_t AppItemCount;
|
||||
int32_t KmsItemCount;
|
||||
int32_t SkuItemCount;
|
||||
int32_t HostBuildCount;
|
||||
int32_t reserved2Counts;
|
||||
};
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
DataPointer_t Datapointers[3];
|
||||
DataPointer_t Datapointers[5];
|
||||
|
||||
struct
|
||||
{
|
||||
@ -324,19 +351,31 @@ typedef struct VlmcsdHeader
|
||||
PVlmcsdData_t SkuItemList;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t HostBuildOffset;
|
||||
PHostBuild_t HostBuildList;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
uint64_t Reserved2Offset;
|
||||
void* Reserved2List;
|
||||
};
|
||||
|
||||
CsvlkData_t CsvlkData[1];
|
||||
};
|
||||
};
|
||||
|
||||
} VlmcsdHeader_t, *PVlmcsdHeader_t;
|
||||
|
||||
#define EPID_INDEX_WINDOWS 0
|
||||
#define EPID_INDEX_OFFICE2010 1
|
||||
#define EPID_INDEX_OFFICE2013 2
|
||||
#define EPID_INDEX_OFFICE2016 3
|
||||
#define EPID_INDEX_WINCHINAGOV 4
|
||||
//#define EPID_INDEX_WINDOWS 0
|
||||
//#define EPID_INDEX_OFFICE2010 1
|
||||
//#define EPID_INDEX_OFFICE2013 2
|
||||
//#define EPID_INDEX_OFFICE2016 3
|
||||
//#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 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);
|
||||
void randomPidInit();
|
||||
void get16RandomBytes(void* ptr);
|
||||
RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* Response_v6, int responseSize, BYTE* const response, const BYTE* const request, BYTE* hwid);
|
||||
RESPONSE_RESULT DecryptResponseV4(RESPONSE_V4* Response_v4, const int responseSize, BYTE* const response, const BYTE* const request);
|
||||
void getUnixTimeAsFileTime(FILETIME *const ts);
|
||||
__pure int64_t fileTimeToUnixTime(const FILETIME *const ts);
|
||||
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 rawResponse, const BYTE* const rawRequest);
|
||||
void getUnixTimeAsFileTime(FILETIME* ts);
|
||||
__pure int64_t fileTimeToUnixTime(FILETIME* ts);
|
||||
|
||||
#ifndef IS_LIBRARY
|
||||
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
|
||||
|
||||
#ifndef NO_STRICT_MODES
|
||||
@ -362,7 +404,7 @@ extern RequestCallback_t CreateResponseBase;
|
||||
|
||||
#ifdef _PEDANTIC
|
||||
uint16_t IsValidLcid(const uint16_t lcid);
|
||||
uint16_t IsValidHostBuild(const uint16_t hostBuild);
|
||||
uint32_t IsValidHostBuild(const int32_t hostBuild);
|
||||
#endif // _PEDANTIC
|
||||
|
||||
#endif // __kms_h
|
||||
|
1853
src/kmsdata-full.c
1853
src/kmsdata-full.c
File diff suppressed because it is too large
Load Diff
2195
src/kmsdata.c
2195
src/kmsdata.c
File diff suppressed because it is too large
Load Diff
@ -171,7 +171,7 @@ RpcStatus closeRpc(const RpcCtx handle)
|
||||
|
||||
#if !MULTI_CALL_BINARY
|
||||
// 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);
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ int ProcessActivationRequest(handle_t IDL_handle, int requestSize, unsigned char
|
||||
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -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 "".
|
||||
*/
|
||||
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)
|
||||
{
|
||||
uint8_t tmp[NS_MAXCDNAME];
|
||||
|
@ -3,7 +3,7 @@
|
||||
#define NS_NAME_H_
|
||||
|
||||
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);
|
||||
|
||||
#endif /* NS_NAME_H_ */
|
||||
|
@ -57,9 +57,9 @@
|
||||
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++)
|
||||
if (!*p) return p-s+1;
|
||||
else if (*p>=192)
|
||||
@ -69,8 +69,8 @@ static int dn_skipname_vlmcsd(const unsigned char *s, const unsigned char *end)
|
||||
}
|
||||
|
||||
static int
|
||||
ns_skiprr_vlmcsd(const uint8_t *ptr, const uint8_t *eom, ns_sect_vlmcsd section, int count) {
|
||||
const uint8_t *optr = ptr;
|
||||
ns_skiprr_vlmcsd(uint8_t *ptr, uint8_t *eom, ns_sect_vlmcsd section, int count) {
|
||||
uint8_t *optr = ptr;
|
||||
|
||||
for ((void)NULL; count > 0; count--) {
|
||||
int b, rdlength;
|
||||
@ -93,8 +93,8 @@ ns_skiprr_vlmcsd(const uint8_t *ptr, const uint8_t *eom, ns_sect_vlmcsd section,
|
||||
}
|
||||
|
||||
int
|
||||
ns_initparse_vlmcsd(const uint8_t *msg, int msglen, ns_msg_vlmcsd *handle) {
|
||||
const uint8_t *eom = msg + msglen;
|
||||
ns_initparse_vlmcsd(uint8_t *msg, int msglen, ns_msg_vlmcsd *handle) {
|
||||
uint8_t *eom = msg + msglen;
|
||||
int i;
|
||||
|
||||
memset(handle, 0x5e, sizeof *handle);
|
||||
|
@ -46,12 +46,12 @@ typedef enum __ns_sect_vlmcsd {
|
||||
} ns_sect_vlmcsd;
|
||||
|
||||
typedef struct __ns_msg_vlmcsd {
|
||||
const uint8_t *_msg, *_eom;
|
||||
uint8_t *_msg, *_eom;
|
||||
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;
|
||||
int _rrnum;
|
||||
const uint8_t *_msg_ptr;
|
||||
uint8_t *_msg_ptr;
|
||||
} ns_msg_vlmcsd;
|
||||
|
||||
|
||||
@ -61,10 +61,10 @@ typedef struct __ns_rr_vlmcsd {
|
||||
uint16_t rr_class;
|
||||
uint32_t ttl;
|
||||
uint16_t rdlength;
|
||||
const uint8_t * rdata;
|
||||
uint8_t * rdata;
|
||||
} 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);
|
||||
|
||||
|
@ -180,7 +180,7 @@ void uuid2StringLE(const GUID *const guid, char *const string)
|
||||
}
|
||||
|
||||
#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 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));
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
|
@ -14,8 +14,8 @@ typedef int (*PRINTFUNC)(const char *const fmt, ...);
|
||||
|
||||
int printerrorf(const char *const fmt, ...);
|
||||
int errorout(const char* fmt, ...);
|
||||
void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p);
|
||||
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, const RESPONSE *const response, const PRINTFUNC p);
|
||||
void logRequestVerbose(REQUEST* Request, const PRINTFUNC p);
|
||||
void logResponseVerbose(const char *const ePID, const BYTE *const hwid, RESPONSE* response, const PRINTFUNC p);
|
||||
|
||||
#ifndef NO_VERSION_INFORMATION
|
||||
void printPlatform();
|
||||
|
@ -325,7 +325,7 @@ static int rpcRequest(const RPC_REQUEST64 *const Request, RPC_RESPONSE64 *const
|
||||
# endif // !SIMPLE_RPC
|
||||
|
||||
pRpcReturnCode = ((BYTE*)&Response->Ndr) + len;
|
||||
UA32(pRpcReturnCode) = ResponseSize < 0 ? LE32(ResponseSize) : 0;
|
||||
PUT_UA32LE(pRpcReturnCode, ResponseSize < 0 ? ResponseSize : 0);
|
||||
len += sizeof(DWORD);
|
||||
|
||||
// Pad zeros to 32-bit align (seems not neccassary but Windows RPC does it this way)
|
||||
@ -970,7 +970,8 @@ RpcStatus rpcSendRequest(const RpcCtx sock, const BYTE *const kmsRequest, const
|
||||
}
|
||||
|
||||
pReturnCode = (DWORD*)(*kmsResponse + *responseSize + pad);
|
||||
status = LE32(UA32(pReturnCode));
|
||||
status = GET_UA32LE(pReturnCode);
|
||||
//status = LE32(UA32(pReturnCode));
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ typedef struct
|
||||
const BYTE* HwId;
|
||||
#ifndef NO_LOG
|
||||
const char* EpidSource;
|
||||
uint8_t IsRandom;
|
||||
#endif // NO_LOG
|
||||
} KmsResponseParam_t, *PKmsResponseParam_t;
|
||||
|
||||
|
99
src/vlmcs.c
99
src/vlmcs.c
@ -52,8 +52,6 @@
|
||||
#define VLMCS_OPTION_GRAB_INI 1
|
||||
#define VLMCS_OPTION_NO_GRAB_INI 2
|
||||
|
||||
//#define kmsVersionMinor 0 // Currently constant. May change in future KMS versions
|
||||
|
||||
#ifndef IS_LIBRARY
|
||||
|
||||
// Function Prototypes
|
||||
@ -83,24 +81,19 @@ static int AddressFamily = 0;
|
||||
static int_fast8_t incompatibleOptions = 0;
|
||||
static const char* fn_ini_client = NULL;
|
||||
//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 NCountPolicy = 0;
|
||||
static GUID AppGuid, KmsGuid, SkuGuid;
|
||||
static uint16_t MinorVersion = 0;
|
||||
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
|
||||
static int_fast8_t NoSrvRecordPriority = FALSE;
|
||||
#endif // NO_DNS
|
||||
|
||||
|
||||
typedef char iniFileEpidLines[4][256];
|
||||
//typedef char iniFileEpidLines[4][256];
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
struct stat statbuf;
|
||||
# endif
|
||||
@ -975,7 +967,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
|
||||
int_fast8_t iniFileExistedBefore = TRUE;
|
||||
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);
|
||||
|
||||
@ -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.
|
||||
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));
|
||||
exit(error);
|
||||
}
|
||||
@ -1023,7 +1015,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
|
||||
|
||||
if (!in)
|
||||
{
|
||||
int error = errno;
|
||||
const int error = errno;
|
||||
errorout("Fatal: Cannot open %s: %s\n", fn_bak, strerror(error));
|
||||
exit(error);
|
||||
}
|
||||
@ -1032,7 +1024,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
|
||||
|
||||
if (!out)
|
||||
{
|
||||
int error = errno;
|
||||
const int error = errno;
|
||||
errorout("Fatal: Cannot create %s: %s\n", fn_ini_client, strerror(error));
|
||||
exit(error);
|
||||
}
|
||||
@ -1041,9 +1033,9 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
|
||||
|
||||
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;
|
||||
|
||||
@ -1054,7 +1046,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= vlmcsd_countof(*lines))
|
||||
if (i >= KmsData->CsvlkCount)
|
||||
{
|
||||
fprintf(out, "%s", sourceLine);
|
||||
}
|
||||
@ -1069,7 +1061,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
|
||||
|
||||
fclose(in);
|
||||
|
||||
for (i = 0; i < vlmcsd_countof(*lines); i++)
|
||||
for (i = 0; i < KmsData->CsvlkCount; i++)
|
||||
{
|
||||
if (!lineWritten[i] && *(*lines)[i])
|
||||
{
|
||||
@ -1080,7 +1072,7 @@ static void updateIniFile(iniFileEpidLines* const restrict lines)
|
||||
|
||||
if (fclose(out))
|
||||
{
|
||||
int error = errno;
|
||||
const int error = errno;
|
||||
errorout("Fatal: Cannot write to %s: %s\n", fn_ini_client, strerror(error));
|
||||
exit(error);
|
||||
}
|
||||
@ -1095,18 +1087,27 @@ static void grabServerData()
|
||||
{
|
||||
RpcCtx s = INVALID_RPCCTX;
|
||||
WORD MajorVer = 6;
|
||||
iniFileEpidLines lines;
|
||||
|
||||
static char* Licenses[vlmcsd_countof(lines)] =
|
||||
{
|
||||
(char*)"212a64dc-43b1-4d3d-a30c-2fc69d2095c6", // Vista
|
||||
(char*)"e85af946-2e25-47b7-83e1-bebcebeac611", // Office 2010
|
||||
(char*)"e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0", // Office 2013
|
||||
(char*)"85b5f61b-320b-4be3-814a-b76b2bfafc82", // Office 2016
|
||||
};
|
||||
|
||||
uint_fast8_t i;
|
||||
int32_t i;
|
||||
int32_t j;
|
||||
|
||||
char** lines = (char**)vlmcsd_malloc(KmsData->CsvlkCount * sizeof(char*));
|
||||
GUID* kmsGuids = (GUID*)vlmcsd_malloc(KmsData->CsvlkCount * sizeof(GUID));
|
||||
|
||||
for (i = 0; i < KmsData->CsvlkCount; i++)
|
||||
{
|
||||
lines[i] = (char*)vlmcsd_malloc(256);
|
||||
*lines[i] = 0;
|
||||
|
||||
for (j = 0; j < KmsData->KmsItemCount; j++)
|
||||
{
|
||||
if (KmsData->KmsItemList[j].EPidIndex == i)
|
||||
{
|
||||
kmsGuids[i] = KmsData->KmsItemList[j].Guid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RESPONSE response;
|
||||
RESPONSE_RESULT result;
|
||||
REQUEST request;
|
||||
@ -1114,23 +1115,19 @@ static void grabServerData()
|
||||
int status;
|
||||
size_t len;
|
||||
|
||||
for (i = 0; i < vlmcsd_countof(lines); i++) *lines[i] = 0;
|
||||
|
||||
for (i = 0; i < vlmcsd_countof(Licenses) && MajorVer > 3; i++)
|
||||
for (i = 0; i < KmsData->CsvlkCount && MajorVer > 3; i++)
|
||||
{
|
||||
GUID guid;
|
||||
string2UuidLE(Licenses[i], &guid);
|
||||
int32_t kmsIndex = getProductIndex(&guid, KmsData->KmsItemList, KmsData->KmsItemCount, NULL, NULL);
|
||||
const int32_t kmsIndex = getProductIndex(&kmsGuids[i], KmsData->KmsItemList, KmsData->KmsItemCount, NULL, NULL);
|
||||
|
||||
if (kmsIndex < 0)
|
||||
{
|
||||
errorout("Warning: KMS GUID %s not in database.\n", Licenses[i]);
|
||||
errorout("Warning: KMS GUID not in database.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
ActiveProductIndex = ~0;
|
||||
|
||||
for (j = KmsData->SkuItemCount; j >= 0; j--)
|
||||
for (j = KmsData->SkuItemCount - 1; j >= 0; j--)
|
||||
{
|
||||
if (KmsData->SkuItemList[j].KmsIndex == kmsIndex)
|
||||
{
|
||||
@ -1141,11 +1138,11 @@ static void grabServerData()
|
||||
|
||||
if (ActiveProductIndex == ~0)
|
||||
{
|
||||
errorout("Warning: KMS GUID %s not in database.\n", Licenses[i]);
|
||||
errorout("Warning: KMS GUID not in database.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t appIndex = KmsData->SkuItemList[ActiveProductIndex].AppIndex;
|
||||
const int32_t appIndex = KmsData->SkuItemList[ActiveProductIndex].AppIndex;
|
||||
|
||||
NCountPolicy = (uint32_t)KmsData->SkuItemList[ActiveProductIndex].NCountPolicy;
|
||||
memcpy(&SkuGuid, &KmsData->SkuItemList[ActiveProductIndex].Guid, sizeof(GUID));
|
||||
@ -1154,7 +1151,7 @@ static void grabServerData()
|
||||
MajorVersion = (uint16_t)MajorVer;
|
||||
|
||||
status = sendRequest(&s, &request, &response, hwid, &result);
|
||||
printf("%-11s", ePidGroup[i]);
|
||||
printf("%-11s", getNextString(KmsData->CsvlkData[i].EPid));
|
||||
|
||||
if (status)
|
||||
{
|
||||
@ -1171,7 +1168,7 @@ static void grabServerData()
|
||||
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);
|
||||
|
||||
char ePID[3 * PID_BUFFER_SIZE];
|
||||
@ -1181,16 +1178,16 @@ static void grabServerData()
|
||||
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)
|
||||
{
|
||||
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]);
|
||||
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
|
||||
{
|
||||
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
|
||||
|
||||
WSADATA wsadata;
|
||||
WSADATA wsaData;
|
||||
int error;
|
||||
|
||||
if ((error = WSAStartup(0x0202, &wsadata)))
|
||||
if ((error = WSAStartup(0x0202, &wsaData)))
|
||||
{
|
||||
errorout("Fatal: Could not initialize Windows sockets (Error: %d).\n", error);
|
||||
return error;
|
||||
@ -1245,7 +1242,7 @@ int client_main(int argc, CARGV argv)
|
||||
else
|
||||
useDefaultHost = TRUE;
|
||||
|
||||
int hostportarg = optind;
|
||||
const int hostportarg = optind;
|
||||
|
||||
if (optind < argc - 1)
|
||||
{
|
||||
|
105
src/vlmcsd.c
105
src/vlmcsd.c
@ -101,13 +101,15 @@ static const char *restrict ServicePassword = "";
|
||||
static const char* fn_pid = NULL;
|
||||
#endif
|
||||
|
||||
#ifndef NO_INI_FILE
|
||||
#if !defined(NO_INI_FILE) || !defined(NO_CL_PIDS)
|
||||
|
||||
#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
|
||||
#endif // NO_INI_FILE
|
||||
|
||||
#ifndef NO_TAP
|
||||
char* tapArgument = NULL;
|
||||
@ -380,7 +382,7 @@ static __noreturn void usage()
|
||||
|
||||
|
||||
#ifndef NO_CUSTOM_INTERVALS
|
||||
#ifndef NO_INI_FILE
|
||||
#if !defined(NO_INI_FILE)
|
||||
|
||||
__pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char* const restrict argument)
|
||||
{
|
||||
@ -396,7 +398,7 @@ __pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char *const restr
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif // NO_INI_FILE
|
||||
#endif // !defined(NO_INI_FILE)
|
||||
|
||||
|
||||
__pure static DWORD getTimeSpanFromCommandLine(const char* const restrict arg, const char optchar)
|
||||
@ -478,24 +480,6 @@ static BOOL setEpidFromIniFileLine(const char **s, const uint32_t index, const c
|
||||
|
||||
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
|
||||
static BOOL getIniFileArgumentBool(int_fast8_t* result, const char* const argument)
|
||||
@ -749,6 +733,8 @@ static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
|
||||
|
||||
return success;
|
||||
}
|
||||
#endif // !NO_INI_FILE
|
||||
|
||||
|
||||
|
||||
static BOOL getIniFileArgument(const char** s)
|
||||
@ -773,10 +759,6 @@ static BOOL getIniFileArgument(const char **s)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char* GetNextString(char* s)
|
||||
{
|
||||
return s + strlen(s) + 1;
|
||||
}
|
||||
|
||||
static int8_t GetCsvlkIndexFromName(const char* s)
|
||||
{
|
||||
@ -784,7 +766,7 @@ static int8_t GetCsvlkIndexFromName(const char *s)
|
||||
|
||||
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)))
|
||||
{
|
||||
@ -824,6 +806,25 @@ static BOOL handleIniFileEpidParameter(const char *s, uint8_t allowIniFileDirect
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#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;
|
||||
@ -866,18 +867,23 @@ static BOOL readIniFile(const uint_fast8_t pass)
|
||||
FILE* restrict f;
|
||||
BOOL result = TRUE;
|
||||
|
||||
if (pass == INI_FILE_PASS_2 && KmsData->MinorVer < 6)
|
||||
{
|
||||
return 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;
|
||||
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);
|
||||
if (*s == ';' || *s == '#' || !*s) continue;
|
||||
@ -1325,14 +1331,6 @@ static void parseGeneralArguments() {
|
||||
case 'H':
|
||||
HostBuild = (uint16_t)getOptionArgumentInt((char)o, 0, 0xffff);
|
||||
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;
|
||||
# endif // NO_RANDOM_PID
|
||||
|
||||
@ -1776,7 +1774,7 @@ int newmain()
|
||||
!IsNDR64Defined
|
||||
)
|
||||
{
|
||||
UseServerRpcNDR64 = !!KmsData->Flags & KMS_OPTIONS_USENDR64;
|
||||
UseServerRpcNDR64 = !!(KmsData->Flags & KMS_OPTIONS_USENDR64);
|
||||
# ifndef NO_RANDOM_EPID
|
||||
if (HostBuild && RandomizationLevel)
|
||||
{
|
||||
@ -1786,13 +1784,6 @@ int newmain()
|
||||
}
|
||||
# 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)
|
||||
KmsResponseParameters = (KmsResponseParam_t*)vlmcsd_malloc(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)
|
||||
{
|
||||
case 'a':
|
||||
if (KmsData->MinorVer < 6 || !handleIniFileEpidParameter(optarg, FALSE, "command line"))
|
||||
if (!handleIniFileEpidParameter(optarg, FALSE, "command line"))
|
||||
{
|
||||
usage();
|
||||
}
|
||||
@ -1905,6 +1896,22 @@ int newmain()
|
||||
// the lifetime of the process. So we generate them now
|
||||
# ifndef NO_RANDOM_EPID
|
||||
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
|
||||
|
||||
# if !defined(NO_SOCKETS)
|
||||
|
@ -28,7 +28,7 @@ int server_main(int argc, CARGV argv);
|
||||
#define SA_NOCLDWAIT 0
|
||||
#endif
|
||||
|
||||
#ifndef NO_INI_FILE
|
||||
#if !defined(NO_INI_FILE) || !defined(NO_CL_PIDS)
|
||||
#define INI_PARAM_RANDOMIZATION_LEVEL 1
|
||||
#define INI_PARAM_LCID 2
|
||||
#define INI_PARAM_LISTEN 3
|
||||
|
28
src/wintap.c
28
src/wintap.c
@ -42,7 +42,7 @@ static BOOL isAddressAssigned()
|
||||
BOOL result = FALSE;
|
||||
|
||||
pIPAddrTable = (PMIB_IPADDRTABLE)vlmcsd_malloc(sizeof(MIB_IPADDRTABLE));
|
||||
DWORD status = GetIpAddrTable(pIPAddrTable, &dwSize, 0);
|
||||
const DWORD status = GetIpAddrTable(pIPAddrTable, &dwSize, 0);
|
||||
free(pIPAddrTable);
|
||||
|
||||
if (status != ERROR_INSUFFICIENT_BUFFER) return FALSE;
|
||||
@ -74,16 +74,16 @@ static BOOL isAddressAssigned()
|
||||
|
||||
static void parseTapArgument(char* argument)
|
||||
{
|
||||
char* equalsignPosition = strchr(argument, (int)'=');
|
||||
char* equalSignPosition = strchr(argument, (int)'=');
|
||||
char* slashPosition = strchr(argument, (int)'/');
|
||||
char* colonPosition = strchr(argument, (int)':');
|
||||
|
||||
szTapName = argument;
|
||||
|
||||
if (equalsignPosition)
|
||||
if (equalSignPosition)
|
||||
{
|
||||
*equalsignPosition = 0;
|
||||
szIpAddress = equalsignPosition + 1;
|
||||
*equalSignPosition = 0;
|
||||
szIpAddress = equalSignPosition + 1;
|
||||
}
|
||||
|
||||
if (slashPosition)
|
||||
@ -166,10 +166,10 @@ static HANDLE OpenTapHandle()
|
||||
WinErrorExit(regResult);
|
||||
}
|
||||
|
||||
char subkeyName[TAP_REGISTRY_DATA_SIZE];
|
||||
DWORD i, subKeySize = sizeof(subkeyName);
|
||||
char subKeyName[TAP_REGISTRY_DATA_SIZE];
|
||||
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;
|
||||
DWORD type, regDataSize;
|
||||
@ -177,7 +177,7 @@ static HANDLE OpenTapHandle()
|
||||
|
||||
if (regResult) WinErrorExit(regResult);
|
||||
|
||||
if ((regResult = RegOpenKeyEx(regAdapterKey, subkeyName, 0, KEY_READ | KEY_WOW64_64KEY, ®SubKey)) == ERROR_SUCCESS)
|
||||
if ((regResult = RegOpenKeyEx(regAdapterKey, subKeyName, 0, KEY_READ | KEY_WOW64_64KEY, ®SubKey)) == ERROR_SUCCESS)
|
||||
{
|
||||
regDataSize = sizeof(regData);
|
||||
|
||||
@ -201,8 +201,8 @@ static HANDLE OpenTapHandle()
|
||||
char connectionKeyName[TAP_REGISTRY_DATA_SIZE];
|
||||
|
||||
strncpy(connectionKeyName, NETWORK_CONNECTIONS_KEY "\\", sizeof(connectionKeyName));
|
||||
strncat(connectionKeyName, regData, sizeof(connectionKeyName));
|
||||
strncat(connectionKeyName, "\\Connection", sizeof(connectionKeyName));
|
||||
strncat(connectionKeyName, regData, sizeof(connectionKeyName) - strlen(connectionKeyName) - 1);
|
||||
strncat(connectionKeyName, "\\Connection", sizeof(connectionKeyName) - strlen(connectionKeyName) - 1);
|
||||
|
||||
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);
|
||||
strncpy(deviceName, USERMODEDEVICEDIR, sizeof(deviceName));
|
||||
strncat(deviceName, regData, sizeof(deviceName));
|
||||
strncat(deviceName, strcmp(AdapterClass, "TEAMVIEWERVPN") ? TAP_WIN_SUFFIX : ".dgt", sizeof(deviceName));
|
||||
strncat(deviceName, regData, sizeof(deviceName) - strlen(deviceName) - 1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -231,7 +231,7 @@ static HANDLE OpenTapHandle()
|
||||
}
|
||||
|
||||
RegCloseKey(regSubKey);
|
||||
subKeySize = sizeof(subkeyName);
|
||||
subKeySize = sizeof(subKeyName);
|
||||
if (handle != INVALID_HANDLE_VALUE) break;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user