diff --git a/GNUmakefile b/GNUmakefile
index d98cadf..f3cfb3b 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -5,7 +5,10 @@
PROGRAM_NAME ?= vlmcsd
CLIENT_NAME ?= vlmcs
MULTI_NAME ?= vlmcsdmulti
+OBJ_NAME ?= libkms-static.o
+A_NAME ?= libkms.a
CONFIG ?= config.h
+COMPILER_LANGUAGE ?= c
# crypto library to use for standard algos, could save ~1-2kb ;)
# can be either 'openssl', 'polarssl' or anything other for internal impl
@@ -34,49 +37,72 @@ endif
ifneq (,$(findstring androideabi,$(TARGETPLATFORM)))
ANDROID := 1
UNIX := 1
+ ELF := 1
endif
ifneq (,$(findstring minix,$(TARGETPLATFORM)))
MINIX := 1
UNIX := 1
+ ELF := 1
endif
ifneq (,$(findstring mingw,$(TARGETPLATFORM)))
MINGW := 1
WIN := 1
+ PE := 1
endif
ifneq (,$(findstring cygwin,$(TARGETPLATFORM)))
CYGWIN := 1
WIN := 1
+ PE := 1
+endif
+
+ifneq (,$(findstring cygnus,$(TARGETPLATFORM)))
+ CYGWIN := 1
+ WIN := 1
+ PE := 1
endif
ifneq (,$(findstring freebsd,$(TARGETPLATFORM)))
FREEBSD := 1
UNIX := 1
BSD := 1
+ ELF := 1
endif
ifneq (,$(findstring netbsd,$(TARGETPLATFORM)))
NETBSD := 1
UNIX := 1
BSD := 1
+ ELF := 1
endif
ifneq (,$(findstring openbsd,$(TARGETPLATFORM)))
OPENBSD := 1
UNIX := 1
BSD := 1
+ ELF := 1
endif
ifneq (,$(findstring solaris,$(TARGETPLATFORM)))
SOLARIS := 1
UNIX := 1
+ ELF := 1
endif
ifneq (,$(findstring linux,$(TARGETPLATFORM)))
LINUX := 1
UNIX := 1
+ ELF := 1
+endif
+
+ifneq (,$(findstring gnu,$(TARGETPLATFORM)))
+ifeq (,$(findstring linux,$(TARGETPLATFORM)))
+ UNIX := 1
+ HURD := 1
+ ELF := 1
+endif
endif
ifeq ($(CYGWIN),1)
@@ -89,12 +115,25 @@ else
DLL_NAME ?= libkms.so
endif
-BASECFLAGS = -DCONFIG=\"$(CONFIG)\" -DBUILD_TIME=$(shell date '+%s') -g -Os -fno-strict-aliasing -fomit-frame-pointer -ffunction-sections -fdata-sections
+BASECFLAGS = -DVLMCSD_COMPILER=\"$(notdir $(CC))\" -DVLMCSD_PLATFORM=\"$(TARGETPLATFORM)\" -DCONFIG=\"$(CONFIG)\" -DBUILD_TIME=$(shell date '+%s') -g -Os -fno-strict-aliasing -fomit-frame-pointer -ffunction-sections -fdata-sections
BASELDFLAGS =
STRIPFLAGS =
CLIENTLDFLAGS =
SERVERLDFLAGS =
+ifndef SAFE_MODE
+ BASECFLAGS += -fvisibility=hidden -pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants
+
+ ifeq ($(ELF),1)
+ BASELDFLAGS += -Wl,-z,norelro
+ endif
+
+ ifneq (,$(findstring gcc,$(notdir $(CC))))
+ BASECFLAGS += -flto
+ endif
+
+endif
+
ifeq ($(NOLIBS),1)
NOLRESOLV=1
NOLPTHREAD=1
@@ -105,20 +144,24 @@ ifneq ($(NO_DNS),1)
ifneq ($(NOLRESOLV),1)
ifeq ($(MINGW),1)
- BASELDFLAGS += -ldnsapi
+ CLIENTLDFLAGS += -ldnsapi
endif
ifeq ($(LINUX),1)
- BASELDFLAGS += -lresolv
+ CLIENTLDFLAGS += -lresolv
+ endif
+
+ ifeq ($(HURD),1)
+ CLIENTLDFLAGS += -lresolv
endif
ifeq ($(DARWIN),1)
- BASELDFLAGS += -lresolv
+ CLIENTLDFLAGS += -lresolv
endif
ifeq ($(CYGWIN),1)
DNS_PARSER := internal
- BASELDFLAGS += -lresolv
+ CLIENTLDFLAGS += -lresolv
endif
ifeq ($(OPENBSD),1)
@@ -126,7 +169,7 @@ ifneq ($(NO_DNS),1)
endif
ifeq ($(SOLARIS),1)
- BASELDFLAGS += -lresolv
+ CLIENTLDFLAGS += -lresolv
endif
endif
@@ -155,16 +198,18 @@ else
STRIPFLAGS += -s
endif
+LIBRARY_CFLAGS = -DSIMPLE_SOCKETS -DNO_TIMEOUT -DNO_SIGHUP -DNO_CL_PIDS -DNO_EXTENDED_PRODUCT_LIST -DNO_BASIC_PRODUCT_LIST -DNO_LOG -DNO_RANDOM_EPID -DNO_INI_FILE -DNO_INI_FILE -DNO_HELP -DNO_CUSTOM_INTERVALS -DNO_PID_FILE -DNO_USER_SWITCH -DNO_VERBOSE_LOG -DNO_LIMIT -DNO_VERSION_INFORMATION
+
ifeq ($(FEATURES), embedded)
- BASECFLAGS += -DNO_HELP -DNO_USER_SWITCH -DNO_BASIC_PRODUCT_LIST -DNO_CUSTOM_INTERVALS -DNO_PID_FILE -DNO_VERBOSE_LOG
+ BASECFLAGS += -DNO_HELP -DNO_USER_SWITCH -DNO_BASIC_PRODUCT_LIST -DNO_CUSTOM_INTERVALS -DNO_PID_FILE -DNO_VERBOSE_LOG -DNO_VERSION_INFORMATION
else ifeq ($(FEATURES), autostart)
- BASECFLAGS += -DNO_HELP
+ BASECFLAGS += -DNO_HELP -DNO_VERSION_INFORMATION
else ifeq ($(FEATURES), minimum)
- BASECFLAGS += -DNO_TIMEOUT -DNO_SIGHUP -DNO_CL_PIDS -DNO_EXTENDED_PRODUCT_LIST -DNO_BASIC_PRODUCT_LIST -DNO_LOG -DNO_RANDOM_EPID -DNO_INI_FILE -DNO_INI_FILE -DNO_HELP -DNO_CUSTOM_INTERVALS -DNO_PID_FILE -DNO_USER_SWITCH -DNO_VERBOSE_LOG -DNO_LIMIT
+ BASECFLAGS += $(LIBRARY_CFLAGS)
else ifeq ($(FEATURES), most)
BASECFLAGS += -DNO_SIGHUP -DNO_PID_FILE -DNO_LIMIT
else ifeq ($(FEATURES), inetd)
- BASECFLAGS += -DNO_SIGHUP -DNO_SOCKETS -DNO_PID_FILE -DNO_LIMIT
+ BASECFLAGS += -DNO_SIGHUP -DNO_SOCKETS -DNO_PID_FILE -DNO_LIMIT -DNO_VERSION_INFORMATION
else ifeq ($(FEATURES), fixedepids)
BASECFLAGS += -DNO_SIGHUP -DNO_CL_PIDS -DNO_RANDOM_EPID -DNO_INI_FILE
endif
@@ -202,7 +247,7 @@ ifdef HWID
endif
ifdef TERMINAL_WIDTH
- BASECFLAGS += -DTERMINAL_FIXED_WIDTH=$(TERMINAL_WIDTH)
+ BASECFLAGS += -DTERMINAL_FIXED_WIDTH=$(TERMINAL_WIDTH) -DDISPLAY_WIDTH=\"$(TERMINAL_WIDTH)\"
endif
ifeq ($(NOPROCFS), 1)
@@ -216,13 +261,15 @@ endif
ifneq ($(ANDROID), 1)
ifneq ($(MINIX), 1)
ifneq ($(NOLPTHREAD), 1)
- ifeq ($(findstring NO_LIMIT,$(CFLAGS) $(BASECFLAGS)),)
- BASELDFLAGS += -lpthread
+
+ ifeq ($(THREADS), 1)
+ SERVERLDFLAGS += -lpthread
+ endif
+
+ ifeq (,$(findstring NO_LIMIT,$(CFLAGS) $(BASECFLAGS)))
+ SERVERLDFLAGS += -lpthread
endif
- ifneq ($(findstring USE_THREADS,$(BASECFLAGS)),)
- BASELDFLAGS += -lpthread
- endif
endif
endif
endif
@@ -283,6 +330,7 @@ ifeq ($(MSRPC),1)
VLMCSD_SRCS += msrpc-server.c
VLMCS_SRCS += msrpc-client.c
MULTI_SRCS += msrpc-server.c msrpc-client.c
+ DLL_SRCS += msrpc-server.c
BASECFLAGS += -DUSE_MSRPC -Wno-unknown-pragmas
BASELDFLAGS += -lrpcrt4
else
@@ -312,7 +360,6 @@ else ifeq ($(CRYPTO), polarssl)
else ifeq ($(CRYPTO), windows)
BASECFLAGS += -D_CRYPTO_WINDOWS
SRCS += crypto_windows.c
- #BASELDFLAGS += -lpolarssl
else
BASECFLAGS += -D_CRYPTO_INTERNAL
SRCS += crypto_internal.c
@@ -332,9 +379,12 @@ endif
ifeq ($(VERBOSE),3)
COMPILER := $(shell printf "%-40s" $(notdir $(CC)))
+ ARCHIVER := $(shell printf "%-40s" $(notdir $(AR)))
endif
-ifeq ($(CAT),2)
+ARCMD := AR
+
+ifdef CAT
LDCMD := CC/LD
else
LDCMD := LD
@@ -344,99 +394,96 @@ endif
%.o: %.c
ifeq ($(VERBOSE),1)
- $(CC) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(PLATFORMFLAGS) -c $<
+ $(CC) -x$(COMPILER_LANGUAGE) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(PLATFORMFLAGS) -c $<
ifeq ($(DEPENDENCIES),1)
- $(CC) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(PLATFORMFLAGS) -MM -MF $*.d $<
+ $(CC) -x$(COMPILER_LANGUAGE) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(PLATFORMFLAGS) -MM -MF $*.d $<
endif
else
@echo "$(COMPILER) CC $@ <- $<"
- @$(CC) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(PLATFORMFLAGS) -c $<
+ @$(CC) -x$(COMPILER_LANGUAGE) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(PLATFORMFLAGS) -c $<
ifeq ($(DEPENDENCIES),1)
@echo "$(COMPILER) DEP $*.d <- $<"
- @$(CC) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(PLATFORMFLAGS) -MM -MF $*.d $<
+ @$(CC) -x$(COMPILER_LANGUAGE) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(PLATFORMFLAGS) -MM -MF $*.d $<
endif
endif
-vlmcsd_all.c: $(VLMCSD_SRCS)
- ifeq ($(VERBOSE),1)
- cat $^ > $@
- else
- @echo "$(COMPILER) CAT $@ <- $^"
- @cat $^ > $@
- endif
-
-vlmcs_all.c: $(VLMCS_SRCS)
- ifeq ($(VERBOSE),1)
- cat $^ > $@
- else
- @echo "$(COMPILER) CAT $@ <- $^"
- @cat $^ > $@
- endif
-
-vlmcsdmulti_all.c: $(MULTI_SRCS)
- ifeq ($(VERBOSE),1)
- cat $^ > $@
- else
- @echo "$(COMPILER) CAT $@ <- $^"
- @cat $^ > $@
- endif
-
ifdef CAT
-ifeq ($(CAT),2)
-$(PROGRAM_NAME): vlmcsd_all.c
+ BUILDCOMMAND = cat $^ | $(CC) -x$(COMPILER_LANGUAGE) -o $@ -
+ VLMCSD_PREREQUISITES = $(VLMCSD_SRCS)
+ VLMCS_PREREQUISITES = $(VLMCS_SRCS)
+ MULTI_PREREQUISITES = $(MULTI_SRCS)
+ DLL_PREREQUISITES = $(DLL_SRCS)
+ OBJ_PREREQUISITES = $(DLL_SRCS)
else
-$(PROGRAM_NAME): vlmcsd_all.o
+ BUILDCOMMAND = $(CC) -o $@ $^
+ VLMCSD_PREREQUISITES = $(VLMCSD_OBJS)
+ VLMCS_PREREQUISITES = $(VLMCS_OBJS)
+ MULTI_PREREQUISITES = $(MULTI_OBJS)
+ DLL_PREREQUISITES = $(DLL_OBJS)
+ OBJ_PREREQUISITES = $(DLL_OBJS)
endif
+
+ifeq ($(VERBOSE),1)
+ BUILDCOMMANDPREFIX = +
else
-$(PROGRAM_NAME): $(VLMCSD_OBJS)
+ BUILDCOMMANDPREFIX = +@
endif
- ifeq ($(VERBOSE),1)
- +$(CC) -o $@ $^ $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS)
- else
- +@echo "$(COMPILER) $(LDCMD) $@ <- $^"
- +@$(CC) -o $@ $^ $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS)
+
+INFOCOMMAND = +@echo "$(COMPILER) $(LDCMD) $@ <- $^"
+ARINFOCOMMAND = +@echo "$(ARCHIVER) $(ARCMD) $@ <. $^"
+
+VLMCSD_COMMAND = $(BUILDCOMMANDPREFIX)$(BUILDCOMMAND) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS) $(SERVERLDFLAGS)
+VLMCS_COMMAND = $(BUILDCOMMANDPREFIX)$(BUILDCOMMAND) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS) $(CLIENTLDFLAGS)
+MULTI_COMMAND = $(BUILDCOMMANDPREFIX)$(BUILDCOMMAND) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS) $(CLIENTLDFLAGS) $(SERVERLDFLAGS)
+DLL_COMMAND = $(BUILDCOMMANDPREFIX)$(BUILDCOMMAND) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS) $(SERVERLDFLAGS) -fvisibility=hidden -shared -DIS_LIBRARY=1 $(LIBRARY_CFLAGS) -UNO_SOCKETS -UUSE_MSRPC
+OBJ_COMMAND = $(BUILDCOMMANDPREFIX)$(BUILDCOMMAND) $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS) $(SERVERLDFLAGS) -fvisibility=hidden -c -DIS_LIBRARY=1 $(LIBRARY_CFLAGS) -UNO_SOCKETS -UUSE_MSRPC
+
+$(PROGRAM_NAME): $(VLMCSD_PREREQUISITES)
+ ifneq ($(VERBOSE),1)
+ $(INFOCOMMAND)
endif
+ $(VLMCSD_COMMAND)
+
+$(CLIENT_NAME): $(VLMCS_PREREQUISITES)
+ ifneq ($(VERBOSE),1)
+ $(INFOCOMMAND)
+ endif
+ $(VLMCS_COMMAND)
+
+$(MULTI_NAME): $(MULTI_PREREQUISITES)
+ ifneq ($(VERBOSE),1)
+ $(INFOCOMMAND)
+ endif
+ $(MULTI_COMMAND)
+
+$(DLL_NAME): $(DLL_PREREQUISITES)
+ ifneq ($(VERBOSE),1)
+ $(INFOCOMMAND)
+ endif
+ $(DLL_COMMAND)
+
+ifndef CAT
+$(OBJ_NAME):
+ +@echo Cannot make $@ without CAT defined. Please create $(A_NAME)
+else
+$(OBJ_NAME): $(OBJ_PREREQUISITES)
+ ifneq ($(VERBOSE),1)
+ $(INFOCOMMAND)
+ endif
+ $(OBJ_COMMAND)
+endif
ifdef CAT
-ifeq ($(CAT),2)
-$(CLIENT_NAME): vlmcs_all.c
+$(A_NAME): $(OBJ_NAME)
else
-$(CLIENT_NAME): vlmcs_all.o
+$(A_NAME): BASECFLAGS += -fvisibility=hidden -DIS_LIBRARY=1 $(LIBRARY_CFLAGS) -UNO_SOCKETS -UUSE_MSRPC
+$(A_NAME): $(DLL_OBJS)
endif
-else
-$(CLIENT_NAME): $(VLMCS_OBJS)
-endif
- ifeq ($(VERBOSE),1)
- +$(CC) -o $@ $^ $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS)
- else
- +@echo "$(COMPILER) $(LDCMD) $@ <- $^"
- +@$(CC) -o $@ $^ $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS)
+ ifneq ($(VERBOSE),1)
+ $(ARINFOCOMMAND)
endif
-
-ifdef CAT
-ifeq ($(CAT),2)
-$(MULTI_NAME): vlmcsdmulti_all.c
-else
-$(MULTI_NAME): vlmcsdmulti_all.o
-endif
-else
-$(MULTI_NAME): $(MULTI_OBJS)
-endif
- ifeq ($(VERBOSE),1)
- +$(CC) -o $@ $^ $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS)
- else
- +@echo "$(COMPILER) $(LDCMD) $@ <- $^"
- +@$(CC) -o $@ $^ $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS)
- endif
-
-$(DLL_NAME): $(DLL_SRCS)
- ifeq ($(VERBOSE),1)
- +$(CC) -o $@ $^ $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS) -shared -DIS_LIBRARY=1 -UNO_SOCKETS -UUSE_MSRPC
- else
- +@echo "$(COMPILER) $(LDCMD) $@ <- $^"
- +@$(CC) -o $@ $^ $(PLATFORMFLAGS) $(BASECFLAGS) $(CFLAGS) $(BASELDFLAGS) $(LDFLAGS) -shared -DIS_LIBRARY=1 -UNO_SOCKETS -UUSE_MSRPC
- endif
-
+ +@rm -f $@
+ $(BUILDCOMMANDPREFIX)$(AR) rcs $@ $^
%.pdf : %
ifeq ($(shell uname), Darwin)
@@ -467,10 +514,10 @@ htmldocs : $(HTMLDOCS)
alldocs : $(UNIXDOCS) $(HTMLDOCS) $(PDFDOCS) $(DOSDOCS)
clean:
- rm -f *.o *.d *_all.c $(PROGRAM_NAME) $(MULTI_NAME) $(DLL_NAME) $(CLIENT_NAME) $(PDFDOCS) $(DOSDOCS) $(UNIXDOCS) $(HTMLDOCS)
+ rm -f *.o *.d *_all.c libkms_all_*.c $(PROGRAM_NAME) $(MULTI_NAME) $(DLL_NAME) $(CLIENT_NAME) $(PDFDOCS) $(DOSDOCS) $(UNIXDOCS) $(HTMLDOCS) $(OBJ_NAME) $(A_NAME) *.a
help:
- @echo "Type:"
+ @echo "Type"
@echo " ${MAKE} - to build $(PROGRAM_NAME) and $(CLIENT_NAME)"
@echo " ${MAKE} clean - to remove $(PROGRAM_NAME) and $(CLIENT_NAME)"
@echo " ${MAKE} help - to see this help"
@@ -485,8 +532,9 @@ help:
@echo " ${MAKE} $(CLIENT_NAME) - to build the client only."
@echo " ${MAKE} $(MULTI_NAME) - to build $(PROGRAM_NAME) and $(CLIENT_NAME) in a single multi-call binary"
@echo " ${MAKE} $(DLL_NAME) - to build the shared library $(DLL_NAME)"
+ @echo " ${MAKE} $(A_NAME) - to build the static library $(A_NAME)"
@echo ""
- @echo "Options:"
+ @echo "Options"
@echo " CONFIG= Compile as instead of config.h."
@echo " INI= Compile $(PROGRAM_NAME) with default ini file "
@echo " PROGRAM_NAME= Use as output file name for the KMS server. Defaults to vlmcsd."
@@ -498,7 +546,10 @@ help:
@echo " CRYPTO=openssl_with_aes_soft EXPERIMENTAL: Use openssl for SHA256/HMAC and AES calculations (software)."
@echo " CRYPTO=polarssl Use polarssl instead of internal crypto code for SHA256/HMAC calculations."
@echo " CRYPTO=windows Use Windows CryptoAPI instead of internal crypto code for SHA256/HMAC calculations."
+ @echo " MSRPC=1 Use Microsoft RPC instead of vlmcsd's internal RPC. Only works with Windows and Cygwin targets."
@echo " CC= Use compiler . Supported compilers are gcc, icc, tcc and clang. Others may or may not work."
+ @echo " AR= Use instead of ar to build $(A_NAME). Set to gcc-ar if you want to use gcc's LTO feature."
+ @echo " COMPILER_LANGUAGE= May be c or c++."
@echo " TERMINAL_WIDTH= Assume a fixed terminal width of columns. Use in case of problems only."
@echo " VLMCSD_VERSION= Sets as your version identifier. Defaults to \"private build\"."
@echo " CFLAGS= Pass as additional arguments to the compiler."
@@ -522,7 +573,7 @@ help:
@echo " FEATURES=minimum Compiles only basic features of $(PROGRAM_NAME)."
@echo " FEATURES=fixedepids $(PROGRAM_NAME) only uses bultin internal ePIDs."
@echo ""
- @echo "Useful CFLAGS to save memory when running $(PROGRAM_NAME) on very small embedded devices (finer control than FEATURES=):"
+ @echo "Useful CFLAGS to save memory when running $(PROGRAM_NAME) on very small embedded devices (finer control than FEATURES=)"
@echo " -DNO_EXTENDED_PRODUCT_LIST Don't compile the detailed product list."
@echo " -DNO_BASIC_PRODUCT_LIST Don't compile the basic product list."
@echo " -DNO_VERBOSE_LOG Don't support verbose logging. Removes -v option."
@@ -533,26 +584,29 @@ help:
@echo " -DNO_USER_SWITCH Don't support changing uid/gid after program start. Removes -u and -g options."
@echo " -DNO_HELP Don't support command line help."
@echo " -DNO_CUSTOM_INTERVALS Don't support custom intervals for retry and refresh activation. Removes -A and -R options."
+ @echo " -DNO_FREEBIND Don't support binding to foreign IP addresses. Removes -F0 and -F1 options. Only affects FreeBSD and Linux."
+ @echo " -DSIMPLE_SOCKETS Compile $(PROGRAM_NAME) with basic socket support only. Removes -L option."
@echo " -DNO_SOCKETS Don't support standalone operation. Requires an internet superserver to start $(PROGRAM_NAME)."
@echo " -DNO_CL_PIDS Don't support specifying ePIDs and HwId from the command line in $(PROGRAM_NAME)."
@echo " -DNO_LIMIT Don't support limiting concurrent clients in $(PROGRAM_NAME)."
@echo " -DNO_SIGHUP Don't support SIGHUP handling in $(PROGRAM_NAME)."
+ @echo " -DNO_VERSION_INFORMATION Don't support displaying version information in $(PROGRAM_NAME) and $(CLIENT_NAME). Removes -V option."
+ @echo " -DENABLE_DEPRECATED_OPTIONS Enable command line options that provide compatibility with previous versions of $(PROGRAM_NAME)."
@echo ""
@echo "Troubleshooting options"
- @echo " CAT=1 Combine all sources in a single file."
- @echo " CAT=2 Combine all sources in a single file and don't create a *.o file."
+ @echo " CAT=1 Combine all sources in a single in-memory file and compile directly to target."
@echo " NOPROCFS=1 Don't rely on a properly mounted proc filesystem in /proc."
@echo " AUXV=1 Use /proc/self/auxv (requires Linux with glibc >= 2.16 or musl.)"
@echo " NOLPTHREAD=1 Disable detection if -lpthread is required (for use with Android NDK)."
- @echo " NOLRESOLV=1 Disable detection if -lresolv is requires (for use with Android NDK)."
+ @echo " NOLRESOLV=1 Disable detection if -lresolv is required (for use with Android NDK)."
@echo " NOLIBS=1 Do not attempt to autodetect any library dependencies."
@echo " OPENSSL_HMAC=0 Compile for openssl versions that don't have HMAC support (required on some embedded devices)."
@echo " NO_TIMEOUT=1 Do not set timeouts for sockets (for systems that don't support it)."
@echo " CHILD_HANDLER=1 Install a handler for SIGCHLD (for systems that don't support SA_NOCLDWAIT)."
- @echo " NO_DNS=1 Compile vlmcs without support for detecting KMS servers via DNS."
+ @echo " NO_DNS=1 Compile $(CLIENT_NAME) without support for detecting KMS servers via DNS."
@echo " DNS_PARSER=internal Use $(CLIENT_NAME) internal DNS parsing routines. No effect on MingW (native Windows)."
@echo ""
- @echo "Other useful CFLAGS:"
+ @echo "Other useful CFLAGS"
@echo " -DSUPPORT_WINE Add code that the Windows version of $(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."
diff --git a/config.h b/config.h
index 221e97d..ffe6bea 100644
--- a/config.h
+++ b/config.h
@@ -37,15 +37,15 @@
*/
#ifndef EPID_WINDOWS
-#define EPID_WINDOWS "06401-00206-271-298329-03-1033-9600.0000-0452015"
+#define EPID_WINDOWS "06401-00206-271-398432-03-1033-9600.0000-1422016"
#endif
#ifndef EPID_OFFICE2010
-#define EPID_OFFICE2010 "06401-00096-199-198322-03-1033-9600.0000-0452015"
+#define EPID_OFFICE2010 "06401-00096-199-198384-03-1033-9600.0000-1422016"
#endif
#ifndef EPID_OFFICE2013
-#define EPID_OFFICE2013 "06401-00206-234-398213-03-1033-9600.0000-0452015"
+#define EPID_OFFICE2013 "06401-00206-234-384729-03-1033-9600.0000-1422016"
#endif
#ifndef HWID // HwId from the Ratiborus VM
@@ -82,6 +82,25 @@
+/*
+ * -------------------------------
+ * Backward compatibility
+ * -------------------------------
+ */
+
+
+#if !defined(ENABLE_DEPRECATED_OPTIONS)
+/*
+ * comment out the following line if you want vlmcsd no to support command line options
+ * that have been present in previous versions of vlmcsd and are now obsolete
+ */
+
+//#define ENABLE_DEPRECATED_OPTIONS
+
+#endif // ENABLE_DEPRECATED_OPTIONS
+
+
+
/*
* ----------------------------------------------------------------------------------------
@@ -366,6 +385,20 @@
*/
+#ifndef NO_FREEBIND
+/*
+ * Do not compile support for FREEBIND (Linux) and IP_BINDANY (FreeBSD). This disables the -F1 command
+ * line option and you can bind only to (listen on) IP addresses that are currently up and running on
+ * your system.
+ */
+
+//#define NO_FREEBIND
+
+#endif // NO_FREEBIND
+
+
+
+
#ifndef NO_EXTENDED_PRODUCT_LIST
/*
* Do not compile the extended product list. Removes the list of Activation GUIDs (aka
@@ -399,6 +432,18 @@
+#ifndef NO_VERSION_INFORMATION
+/*
+ * Removes the -V option from vlmcsd and vlmcs that displays the version information
+ */
+
+//#define NO_VERSION_INFORMATION
+
+#endif // NO_VERSION_INFORMATION
+
+
+
+
#ifndef NO_VERBOSE_LOG
/*
* Removes the ability to do verbose logging and disables -v and -q in vlmcsd. It does not remove the -v
@@ -577,6 +622,19 @@
+#ifndef SIMPLE_SOCKETS
+/*
+ * Disables the ability to choose IP addresses using the -L option in vlmcsd. vlmcsd will listen on all IP addresses.
+ * It still supports IPv4 and IPv6.
+ */
+
+//#define SIMPLE_SOCKETS
+
+#endif // SIMPLE_SOCKETS
+
+
+
+
/* Don't change anything BELOW this line */
diff --git a/floppy144.vfd b/floppy144.vfd
index 1154443..a7220f5 100644
Binary files a/floppy144.vfd and b/floppy144.vfd differ
diff --git a/kms.c b/kms.c
index 840aacc..3287013 100644
--- a/kms.c
+++ b/kms.c
@@ -51,6 +51,7 @@ const KmsIdList ProductList[] = {
};
#endif
+#ifndef IS_LIBRARY
// Application ID is used by KMS server to count KeyManagementServiceCurrentCount
// Do not change the order of this list. Append items as necessary
const KmsIdList AppList[] = {
@@ -59,6 +60,7 @@ const KmsIdList AppList[] = {
/* 002 */ { { 0x0FF1CE15, 0xA989, 0x479D, { 0xaf, 0x46, 0xf2, 0x75, 0xc6, 0x37, 0x06, 0x63 } } /*"0FF1CE15-A989-479D-AF46-F275C6370663"*/, FRIENDLY_NAME_OFFICE2013, EPID_OFFICE2013, 0, 0},
/* 003 */ { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
};
+#endif // IS_LIBRARY
#ifndef NO_EXTENDED_PRODUCT_LIST
const KmsIdList ExtendedProductList [] = {
@@ -258,7 +260,7 @@ static const struct KMSHostOS { uint16_t Type; uint16_t Build; } HostOS[] =
{ 55041, 7601 }, // Windows Server 2008 R2 SP1
{ 5426, 9200 }, // Windows Server 2012
{ 6401, 9600 }, // Windows Server 2012 R2
- { 3612, 10240}, // Windows Server 2016
+ //{ 3612, 10240}, // Windows Server 2016
};
// GroupID and PIDRange
@@ -377,9 +379,10 @@ static int getRandomServerType()
# ifndef USE_MSRPC
else
{
- // return 9200/9600/10240 if NDR64 is in use, otherwise 6002/7601
- if (UseRpcNDR64) return (rand() % 3) + 2;
- return (rand() % 2);
+ // return 9200/9600 if NDR64 is in use, otherwise 6002/7601
+ return (rand() % 2) + (UseRpcNDR64 ? 2 : 0);
+ // if (UseRpcNDR64) return (rand() % 3) + 2;
+ // return (rand() % 2);
}
# endif // USE_MSRPC
}
@@ -424,12 +427,12 @@ static void generateRandomPid(const int index, char *const szPid, int serverType
strcat(szPid, itoc(numberBuffer, HostOS[serverType].Build, 0));
strcat(szPid, ".0000-");
-# define minTime ((time_t)1436958000) // Release Date Windows 10 RTM Escrow
+# define minTime ((time_t)1382029200) // Release Date Win 2012R2
time_t maxTime, kmsTime;
time(&maxTime);
- if (maxTime < minTime) // Just in case the system time is < 07/15/2015 1:00 pm
+ if (maxTime < (time_t)BUILD_TIME) // Just in case the system time is < 10/17/2013 1:00 pm
maxTime = (time_t)BUILD_TIME;
kmsTime = (rand32() % (maxTime - minTime)) + minTime;
@@ -519,6 +522,7 @@ static void logRequest(const REQUEST *const baseRequest)
/*
* Converts a utf-8 ePID string to UCS-2 and writes it to a RESPONSE struct
*/
+#ifndef IS_LIBRARY
static void getEpidFromString(RESPONSE *const Response, const char *const pid)
{
size_t length = utf8_to_ucs2(Response->KmsPID, pid, PID_BUFFER_SIZE, PID_BUFFER_SIZE * 3);
@@ -567,6 +571,7 @@ static void getEpid(RESPONSE *const baseResponse, const char** EpidSource, const
}
getEpidFromString(baseResponse, pid);
}
+#endif // IS_LIBRARY
#if !defined(NO_LOG) && defined(_PEDANTIC)
@@ -627,6 +632,7 @@ static void logResponse(const RESPONSE *const baseResponse, const BYTE *const hw
/*
* Creates the unencrypted base response
*/
+#ifndef IS_LIBRARY
static BOOL __stdcall CreateResponseBaseCallback(const REQUEST *const baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr)
{
const char* EpidSource;
@@ -663,6 +669,13 @@ static BOOL __stdcall CreateResponseBaseCallback(const REQUEST *const baseReques
RequestCallback_t CreateResponseBase = &CreateResponseBaseCallback;
+#else // IS_LIBRARY
+
+RequestCallback_t CreateResponseBase = NULL;
+
+#endif // IS_LIBRARY
+
+
////TODO: Move to helpers.c
void get16RandomBytes(void* ptr)
{
@@ -670,7 +683,6 @@ void get16RandomBytes(void* ptr)
for (i = 0; i < 4; i++) ((DWORD*)ptr)[i] = rand32();
}
-
/*
* Creates v4 response
*/
diff --git a/libkms-test.c b/libkms-test.c
index a808f03..3e22bbf 100644
--- a/libkms-test.c
+++ b/libkms-test.c
@@ -29,7 +29,14 @@ __stdcall BOOL KmsCallBack(const REQUEST *const baseRequest, RESPONSE *const bas
int main(int argc, char** argv)
{
- printf("libvlmcs-test.c: Program start\n");
+ int version = GetLibKmsVersion();
+
+ if (version < 0x30001)
+ {
+ fprintf(stderr, "KMS library version %u.%u or greater required\n", (unsigned int)(version >> 16), (unsigned int)(version & 0xffff));
+ }
+
+ printf("%s: Program start\n", GetEmulatorVersion());
StartKmsServer(1688, KmsCallBack);
return 0;
}
diff --git a/libkms.c b/libkms.c
index 5850131..37ba157 100644
--- a/libkms.c
+++ b/libkms.c
@@ -7,9 +7,13 @@
#endif // CONFIG
#include CONFIG
+#ifdef EXTERNAL
+#undef EXTERNAL
+#endif
+
#define EXTERNAL dllexport
-#define DLLVERSION 0x30000
+#define DLLVERSION 0x30001
#include "libkms.h"
#include "shared_globals.h"
@@ -24,6 +28,10 @@
#include
#endif // WIN32
+#ifdef IS_LIBRARY
+char ErrorMessage[MESSAGE_BUFFER_SIZE];
+#endif // IS_LIBRARY
+
static int_fast8_t IsServerStarted = FALSE;
@@ -42,6 +50,7 @@ EXTERNC __declspec(EXTERNAL) DWORD __cdecl SendActivationRequest
EXTERNC __declspec(EXTERNAL) DWORD __cdecl StartKmsServer(const int port, RequestCallback_t requestCallback)
{
+#ifndef SIMPLE_SOCKETS
char listenAddress[64];
if (IsServerStarted) return !0;
@@ -97,6 +106,39 @@ EXTERNC __declspec(EXTERNAL) DWORD __cdecl StartKmsServer(const int port, Reques
IsServerStarted = FALSE;
return 0;
+
+# else // SIMPLE_SOCKETS
+
+ if (IsServerStarted) return !0;
+ int error;
+
+# ifdef _WIN32
+# ifndef USE_MSRPC
+ // Windows Sockets must be initialized
+ WSADATA wsadata;
+
+ if ((error = WSAStartup(0x0202, &wsadata)))
+ {
+ return error;
+ }
+# endif // USE_MSRPC
+# endif // _WIN32
+
+ defaultport = vlmcsd_malloc(16);
+ snprintf((char*)defaultport, (size_t)16, "%i", port);
+
+ CreateResponseBase = requestCallback;
+ error = listenOnAllAddresses();
+ if (error) return error;
+
+ IsServerStarted = TRUE;
+ runServer();
+ IsServerStarted = FALSE;
+
+ return 0;
+
+
+# endif // SIMPLE_SOCKETS
}
@@ -105,7 +147,11 @@ EXTERNC __declspec(EXTERNAL) DWORD __cdecl StopKmsServer()
if (!IsServerStarted) return !0;
closeAllListeningSockets();
+
+# ifndef SIMPLE_SOCKETS
if (SocketList) free(SocketList);
+# endif
+
return 0;
}
@@ -115,3 +161,9 @@ EXTERNC __declspec(EXTERNAL) int __cdecl GetLibKmsVersion()
return DLLVERSION;
}
+
+EXTERNC __declspec(EXTERNAL) const char* const __cdecl GetEmulatorVersion()
+{
+ return VERSION;
+}
+
diff --git a/libkms.h b/libkms.h
index 2c23cab..1281ce5 100644
--- a/libkms.h
+++ b/libkms.h
@@ -9,24 +9,19 @@
#include "kms.h"
#include "rpc.h"
+#ifndef EXTERNC
#ifdef __cplusplus
-#define EXTERNC extern "C"
+#define EXTERNC EXTERN "C"
#else
#define EXTERNC
#endif
-
-#if !defined(_WIN32) && !__CYGWIN__
-#define __declspec(x) __attribute__((__visibility__("default")))
-#endif
-
-#if !defined(EXTERNAL)
-#define EXTERNAL dllimport
#endif
EXTERNC __declspec(EXTERNAL) DWORD __cdecl SendActivationRequest(const char* const hostname, const int port, RESPONSE* baseResponse, const REQUEST* const baseRequest, RESPONSE_RESULT* result, BYTE *hwid);
EXTERNC __declspec(EXTERNAL) DWORD __cdecl StartKmsServer(const int port, RequestCallback_t requestCallback);
EXTERNC __declspec(EXTERNAL) DWORD __cdecl StopKmsServer();
EXTERNC __declspec(EXTERNAL) int __cdecl GetLibKmsVersion();
+EXTERNC __declspec(EXTERNAL) const char* const __cdecl GetEmulatorVersion();
//EXTERN_C __declspec(EXTERNAL) unsigned int __cdecl GetRandom32();
diff --git a/make_dragonfly b/make_dragonfly
index 2af096d..6afa30e 100755
--- a/make_dragonfly
+++ b/make_dragonfly
@@ -14,6 +14,7 @@ CF45="-static-libgcc -pipe -fno-common -fno-exceptions -fno-stack-protector -fno
CFCLANG="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
LF="-Wl,-z,norelro -Wl,--hash-style=sysv -Wl,--build-id=none"
LFCLANG="-Wl,-z,norelro -Wl,--hash-style=sysv"
+export CC=gcc5
gmake $MAKEFLAGS PROGRAM_NAME=vlmcsd-DragonFly-x64 CLIENT_NAME=vlmcs-DragonFly-x64 CFLAGS="$CF" LDFLAGS="$LF"
rm vlmcsd.o vlmcs.o
diff --git a/make_freebsd b/make_freebsd
index bd4dada..d3d29c3 100755
--- a/make_freebsd
+++ b/make_freebsd
@@ -14,33 +14,33 @@ CFCLANG="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tabl
LF="-Wl,-z,norelro -Wl,--hash-style=gnu -Wl,--build-id=none"
LFCLANG="-Wl,-z,norelro -Wl,--hash-style=gnu"
-gmake $MAKEFLAGS allmulti CAT=2 MULTI_NAME=vlmcsdmulti-FreeBSD-10.2-x64-gcc CLIENT_NAME=vlmcs-FreeBSD-10.2-x64-gcc PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x64-gcc CC=gcc5 CFLAGS="$CF" LDFLAGS="$LF"
+gmake $MAKEFLAGS allmulti CAT=2 MULTI_NAME=vlmcsdmulti-FreeBSD-10.3-x64-gcc CLIENT_NAME=vlmcs-FreeBSD-10.3-x64-gcc PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x64-gcc CC=gcc5 CFLAGS="$CF" LDFLAGS="$LF"
-gmake $MAKEFLAGS CLIENT_NAME=vlmcs-FreeBSD-10.2-x64 PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x64 CC=clang36 CFLAGS="$CFCLANG" LDFLAGS="$LF"
+gmake $MAKEFLAGS CLIENT_NAME=vlmcs-FreeBSD-10.3-x64 PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x64 CC=clang38 CFLAGS="$CFCLANG" LDFLAGS="$LF"
rm -f vlmcs.o vlmcsd.o vlmcsdmulti.o *_all.*
-gmake $REUSEOBJFLAGS vlmcsdmulti-FreeBSD-10.2-x64 MULTI_NAME=vlmcsdmulti-FreeBSD-10.2-x64 CC=clang36 CFLAGS="$CFCLANG" LDFLAGS="$LF"
+gmake $REUSEOBJFLAGS vlmcsdmulti-FreeBSD-10.3-x64 MULTI_NAME=vlmcsdmulti-FreeBSD-10.3-x64 CC=clang38 CFLAGS="$CFCLANG" LDFLAGS="$LF"
-gmake $MAKEFLAGS CLIENT_NAME=vlmcs-FreeBSD-10.2-x86 PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x86 CC=clang36 CFLAGS="$CFCLANG -m32" LDFLAGS="$LF"
+gmake $MAKEFLAGS CLIENT_NAME=vlmcs-FreeBSD-10.3-x86 PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x86 CC=clang38 CFLAGS="$CFCLANG -m32" LDFLAGS="$LF"
rm -f vlmcs.o vlmcsd.o vlmcsdmulti.o *_all.*
-gmake $REUSEOBJFLAGS vlmcsdmulti-FreeBSD-10.2-x86 MULTI_NAME=vlmcsdmulti-FreeBSD-10.2-x86 CC=clang36 CFLAGS="$CFCLANG -m32" LDFLAGS="$LF"
+gmake $REUSEOBJFLAGS vlmcsdmulti-FreeBSD-10.3-x86 MULTI_NAME=vlmcsdmulti-FreeBSD-10.3-x86 CC=clang38 CFLAGS="$CFCLANG -m32" LDFLAGS="$LF"
-gmake $MAKEFLAGS allmulti CAT=2 MULTI_NAME=vlmcsdmulti-FreeBSD-10.2-x86-gcc CLIENT_NAME=vlmcs-FreeBSD-10.2-x86-gcc PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x86-gcc CC=gcc5 CFLAGS="$CF -m32 -DCOMPAT_32BIT" LDFLAGS="-L/usr/lib32 -B/usr/lib32 $LF"
+gmake $MAKEFLAGS allmulti CAT=2 MULTI_NAME=vlmcsdmulti-FreeBSD-10.3-x86-gcc CLIENT_NAME=vlmcs-FreeBSD-10.3-x86-gcc PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x86-gcc CC=gcc5 CFLAGS="$CF -m32 -DCOMPAT_32BIT" LDFLAGS="-L/usr/lib32 -B/usr/lib32 $LF"
-gmake $MAKEFLAGS CAT=2 vlmcsd-FreeBSD-10.2-x64-threads-gcc PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x64-threads-gcc THREADS=1 CC=gcc5 CFLAGS="$CF" LDFLAGS="-lpthread $LF"
-gmake $MAKEFLAGS vlmcsd-FreeBSD-10.2-x64-threads PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x64-threads THREADS=1 CC=clang36 CFLAGS="$CFCLANG" LDFLAGS="-lpthread $LF"
-gmake $MAKEFLAGS vlmcsd-FreeBSD-10.2-x86-threads PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x86-threads THREADS=1 CC=clang36 CFLAGS="$CFCLANG -m32" LDFLAGS="-lpthread $LF"
-gmake $MAKEFLAGS CAT=2 vlmcsd-FreeBSD-10.2-x86-threads-gcc PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x86-threads-gcc THREADS=1 CC=gcc5 CFLAGS="$CF -m32 -DCOMPAT_32BIT" LDFLAGS="-lpthread -L/usr/lib32 -B/usr/lib32 $LF"
+gmake $MAKEFLAGS CAT=2 vlmcsd-FreeBSD-10.3-x64-threads-gcc PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x64-threads-gcc THREADS=1 CC=gcc5 CFLAGS="$CF" LDFLAGS="-lpthread $LF"
+gmake $MAKEFLAGS vlmcsd-FreeBSD-10.3-x64-threads PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x64-threads THREADS=1 CC=clang38 CFLAGS="$CFCLANG" LDFLAGS="-lpthread $LF"
+gmake $MAKEFLAGS vlmcsd-FreeBSD-10.3-x86-threads PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x86-threads THREADS=1 CC=clang38 CFLAGS="$CFCLANG -m32" LDFLAGS="-lpthread $LF"
+gmake $MAKEFLAGS CAT=2 vlmcsd-FreeBSD-10.3-x86-threads-gcc PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x86-threads-gcc THREADS=1 CC=gcc5 CFLAGS="$CF -m32 -DCOMPAT_32BIT" LDFLAGS="-lpthread -L/usr/lib32 -B/usr/lib32 $LF"
-gmake $MAKEFLAGS CRYPTO=openssl_with_aes CLIENT_NAME=vlmcs-FreeBSD-10.2-x64-openssl1.0.1-EXPERIMENTAL PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x64-openssl1.0.1-EXPERIMENTAL CC=clang36 CFLAGS="$CFCLANG" LDFLAGS="$LF"
-gmake $MAKEFLAGS CRYPTO=openssl_with_aes CLIENT_NAME=vlmcs-FreeBSD-10.2-x86-openssl1.0.1-EXPERIMENTAL PROGRAM_NAME=vlmcsd-FreeBSD-10.2-x86-openssl1.0.1-EXPERIMENTAL CC=clang36 CFLAGS="$CFCLANG -m32" LDFLAGS="$LF"
+gmake $MAKEFLAGS CRYPTO=openssl_with_aes CLIENT_NAME=vlmcs-FreeBSD-10.3-x64-openssl1.0.1-EXPERIMENTAL PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x64-openssl1.0.1-EXPERIMENTAL CC=clang38 CFLAGS="$CFCLANG" LDFLAGS="$LF"
+gmake $MAKEFLAGS CRYPTO=openssl_with_aes CLIENT_NAME=vlmcs-FreeBSD-10.3-x86-openssl1.0.1-EXPERIMENTAL PROGRAM_NAME=vlmcsd-FreeBSD-10.3-x86-openssl1.0.1-EXPERIMENTAL CC=clang38 CFLAGS="$CFCLANG -m32" LDFLAGS="$LF"
rm *.o
strip -s --strip-unneeded --remove-section=.eh_frame_hdr --remove-section=.eh_frame --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag vlmcs-* vlmcsd-* vlmcsdmulti-*
sstrip -z vlmcs-* vlmcsd-* vlmcsdmulti-*
-sudo cp -af vlmcsd-FreeBSD-10.2-x86-gcc /usr/local/sbin/vlmcsd
-sudo cp -af vlmcs-FreeBSD-10.2-x86-gcc /usr/local/bin/vlmcs
+sudo cp -af vlmcsd-FreeBSD-10.3-x86-gcc /usr/local/sbin/vlmcsd
+sudo cp -af vlmcs-FreeBSD-10.3-x86-gcc /usr/local/bin/vlmcs
# Copy everything to distribution server
scp -p vlmcsdmulti-* vlmcsd-* vlmcs-* root@ubuntu64:x/binaries/FreeBSD/intel/
diff --git a/make_hurd b/make_hurd
new file mode 100755
index 0000000..9579e48
--- /dev/null
+++ b/make_hurd
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+export VERBOSE=3
+export DNS_PARSER=OS
+
+rm -f vlmcsd-* vlmcs-* vlmcsdmulti-* *_all.* 2>/dev/null
+rm -f vlmcsdmulti vlmcsd vlmcs 2>/dev/null
+
+MAKEFLAGS="-B -j1"
+
+export CC=gcc
+CF="-flto=jobserver -pipe -fwhole-program -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
+LF="-fuse-ld=gold -lresolv -Wl,-z,norelro,--hash-style=gnu,--build-id=none"
+
+make $MAKEFLAGS PROGRAM_NAME=vlmcsd-hurd-x86-glibc CLIENT_NAME=vlmcs-hurd-x86-glibc CFLAGS="$CF" LDFLAGS="$LF" CAT=2
+make $MAKEFLAGS MULTI_NAME=vlmcsdmulti-hurd-x86-glibc vlmcsdmulti-hurd-x86-glibc CFLAGS="$CF" LDFLAGS="$LF" CAT=2 AUXV=1
+
+make clean
+
+sstrip -z vlmcs-* vlmcsd-* vlmcsdmulti-*
+
+cp -af vlmcsd-hurd-x86-glibc /usr/local/sbin/vlmcsd
+cp -af vlmcs-hurd-x86-glibc /usr/local/bin/vlmcs
+
+# Copy man pages
+mkdir -p /usr/local/man/man1 2>/dev/null
+mkdir -p /usr/local/man/man5 2>/dev/null
+mkdir -p /usr/local/man/man8 2>/dev/null
+mkdir -p /usr/local/man/man7 2>/dev/null
+cp -af vlmcs.1 vlmcsdmulti.1 /usr/local/man/man1/
+cp -af vlmcsd.7 /usr/local/man/man7/
+cp -af vlmcsd.8 /usr/local/man/man8/
+cp -af vlmcsd.ini.5 /usr/local/man/man5/
+bzip2 -f -9 /usr/local/man/man5/vlmcsd.ini.5 /usr/local/man/man1/vlmcs.1 /usr/local/man/man1/vlmcsdmulti.1 /usr/local/man/man7/vlmcsd.7 /usr/local/man/man8/vlmcsd.8
+
+# Copy everything to distribution server
+scp -p vlmcsdmulti-* vlmcsd-* vlmcs-* root@ubuntu64.internal:x/binaries/Hurd/intel/
+
diff --git a/make_kfreebsd b/make_kfreebsd
new file mode 100755
index 0000000..acc382f
--- /dev/null
+++ b/make_kfreebsd
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+export VERBOSE=3
+export DNS_PARSER=OS
+
+rm -f vlmcsd-* vlmcs-* vlmcsdmulti-* *_all.* 2>/dev/null
+rm -f vlmcsdmulti vlmcsd vlmcs 2>/dev/null
+
+MAKEFLAGS="-B -j`nproc`"
+
+export CC=gcc
+CF="-flto=jobserver -pipe -fwhole-program -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
+LF="-lresolv -Wl,-z,norelro,--hash-style=gnu,--build-id=none"
+
+export PROGRAM_NAME=vlmcsd-FreeBSD-10.1-x64-glibc
+export CLIENT_NAME=vlmcs-FreeBSD-10.1-x64-glibc
+export MULTI_NAME=vlmcsdmulti-FreeBSD-10.1-x64-glibc
+
+make $MAKEFLAGS CFLAGS="$CF -m64" LDFLAGS="$LF" CAT=2
+make $MAKEFLAGS $MULTI_NAME CFLAGS="$CF -m64" LDFLAGS="$LF" CAT=2 AUXV=1
+
+export PROGRAM_NAME=vlmcsd-FreeBSD-10.1-x86-glibc
+export CLIENT_NAME=vlmcs-FreeBSD-10.1-x86-glibc
+export MULTI_NAME=vlmcsdmulti-FreeBSD-10.1-x86-glibc
+
+make $MAKEFLAGS CFLAGS="$CF -m32" LDFLAGS="$LF" CAT=2
+make $MAKEFLAGS $MULTI_NAME CFLAGS="$CF -m32" LDFLAGS="$LF" CAT=2 AUXV=1
+
+sstrip -z vlmcs-* vlmcsd-* vlmcsdmulti-*
+
+cp -af $PROGRAM_NAME /usr/local/sbin/vlmcsd
+cp -af $CLIENT_NAME /usr/local/bin/vlmcs
+
+# Copy man pages
+mkdir -p /usr/local/man/man1 2>/dev/null
+mkdir -p /usr/local/man/man5 2>/dev/null
+mkdir -p /usr/local/man/man8 2>/dev/null
+mkdir -p /usr/local/man/man7 2>/dev/null
+cp -af vlmcs.1 vlmcsdmulti.1 /usr/local/man/man1/
+cp -af vlmcsd.7 /usr/local/man/man7/
+cp -af vlmcsd.8 /usr/local/man/man8/
+cp -af vlmcsd.ini.5 /usr/local/man/man5/
+bzip2 -f -9 /usr/local/man/man5/vlmcsd.ini.5 /usr/local/man/man1/vlmcs.1 /usr/local/man/man1/vlmcsdmulti.1 /usr/local/man/man7/vlmcsd.7 /usr/local/man/man8/vlmcsd.8
+
+# Copy everything to distribution server
+scp -p vlmcsdmulti-* vlmcsd-* vlmcs-* root@ubuntu64.internal:x/binaries/FreeBSD/intel/
+
diff --git a/make_linux b/make_linux
index 4fad250..b2f474b 100755
--- a/make_linux
+++ b/make_linux
@@ -20,7 +20,7 @@ mkdir -p binaries/Linux/intel/uclibc
mkdir -p binaries/Linux/intel/static
mkdir -p binaries/Linux/intel/musl
-mkdir -p binaries/Linux/sparc32/glibc
+mkdir -p binaries/Linux/sparc/glibc
mkdir -p binaries/Linux/s390/glibc
mkdir -p binaries/Android/arm/bionic
@@ -62,10 +62,13 @@ mkdir -p binaries/DragonFly/intel
mkdir -p binaries/Solaris/intel
mkdir -p binaries/Windows/intel
mkdir -p binaries/Minix/intel
+mkdir -p binaries/Hurd/intel
rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
export STAGING_DIR=.
+
+
# Windows 32-bit using MingW32-w64 toolchain on Ubuntu Linux
export CLIENT_NAME=binaries/Windows/intel/vlmcs-Windows-x86.exe
export PROGRAM_NAME=binaries/Windows/intel/vlmcsd-Windows-x86.exe
@@ -75,10 +78,10 @@ export THREADS=1
export CFLAGS="$SMALLCC"
export CC=i686-w64-mingw32-gcc
export PLATFORMFLAGS="-march=i686 -mtune=generic -fwhole-program -pipe"
-export LDFLAGS="-lws2_32 -Wl,--gc-sections,--force-exe-suffix,--large-address-aware,--nxcompat,--dynamicbase,--tsaware"
+export LDFLAGS="-lws2_32 -Wl,--gc-sections,--force-exe-suffix,--large-address-aware,--nxcompat,--dynamicbase,--tsaware,--no-seh,--disable-long-section-names"
export FEATURES=full
-make $MAKEFLAGS CAT=2 all $MULTI_NAME
+make $MAKEFLAGS CRYPTO=windows CAT=2 all $MULTI_NAME
if [ $? != 0 ]; then
echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
@@ -88,7 +91,7 @@ fi
export CFLAGS="$CFLAGS -flto=jobserver -fvisibility=hidden"
export LDFLAGS="$LDFLAGS -static-libgcc"
-make $MAKEFLAGS FEATURES=minimum $DLL_NAME
+make $MAKEFLAGS CRYPTO=windows FEATURES=minimum $DLL_NAME
if [ $? != 0 ]; then
echo Error creating $DLL_NAME
@@ -105,17 +108,28 @@ export THREADS=1
export CFLAGS="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fmerge-all-constants -Wno-unused-variable -Wno-missing-braces"
export CC=i686-w64-mingw32-gcc
export PLATFORMFLAGS="-march=i686 -mtune=generic -pipe"
-export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--large-address-aware,--nxcompat,--dynamicbase,--tsaware -fwhole-program"
+export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--large-address-aware,--nxcompat,--dynamicbase,--tsaware,--disable-long-section-names -fwhole-program"
export FEATURES=full
-make $MAKEFLAGS CAT=2 MSRPC=1 all
+make $MAKEFLAGS CAT=2 MSRPC=1 CRYPTO=windows $CLIENT_NAME
if [ $? != 0 ]; then
- echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ echo Error creating $CLIENT_NAME
exit $?
fi
-make $MAKEFLAGS MSRPC=1 $MULTI_NAME
+export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--large-address-aware,--nxcompat,--dynamicbase,--tsaware,--disable-long-section-names,--no-seh -fwhole-program"
+
+make $MAKEFLAGS CAT=2 MSRPC=1 CRYPTO=windows $PROGRAM_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $PROGRAM_NAME
+ exit $?
+fi
+
+export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--large-address-aware,--nxcompat,--dynamicbase,--tsaware,--disable-long-section-names -fwhole-program"
+
+make $MAKEFLAGS MSRPC=1 CRYPTO=windows $MULTI_NAME
if [ $? != 0 ]; then
echo Error creating $MULTI_NAME
@@ -133,9 +147,9 @@ export THREADS=1
export CFLAGS="$SMALLCC"
export CC=x86_64-w64-mingw32-gcc
export PLATFORMFLAGS="-march=nocona -mtune=generic -fwhole-program -pipe"
-export LDFLAGS="-lws2_32 -Wl,--gc-sections,--force-exe-suffix,--nxcompat,--dynamicbase,--tsaware"
+export LDFLAGS="-lws2_32 -Wl,--gc-sections,--force-exe-suffix,--nxcompat,--dynamicbase,--tsaware,--no-seh,--high-entropy-va,--disable-long-section-names"
-make $MAKEFLAGS CAT=2 all $MULTI_NAME
+make $MAKEFLAGS CAT=2 CRYPTO=windows all $MULTI_NAME
if [ $? != 0 ]; then
echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
@@ -145,7 +159,7 @@ fi
export CFLAGS="$CFLAGS -flto=jobserver -fvisibility=hidden"
export LDFLAGS="$LDFLAGS -static-libgcc"
-make $MAKEFLAGS FEATURES=minimum $DLL_NAME
+make $MAKEFLAGS CRYPTO=windows FEATURES=minimum $DLL_NAME
if [ $? != 0 ]; then
echo Error creating $DLL_NAME
@@ -163,22 +177,85 @@ export THREADS=1
export CFLAGS="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fmerge-all-constants -Wno-unused-variable -Wno-missing-braces"
export CC=x86_64-w64-mingw32-gcc
export PLATFORMFLAGS="-march=nocona -mtune=generic -pipe"
-export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--nxcompat,--dynamicbase,--tsaware -fwhole-program"
+export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--nxcompat,--dynamicbase,--tsaware,--high-entropy-va,--disable-long-section-names -fwhole-program"
-make $MAKEFLAGS CAT=2 MSRPC=1 all
+make $MAKEFLAGS CAT=2 CRYPTO=windows MSRPC=1 $CLIENT_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME
+ exit $?
+fi
+
+export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--nxcompat,--dynamicbase,--tsaware,--no-seh,--high-entropy-va,--disable-long-section-names -fwhole-program"
+
+make $MAKEFLAGS CAT=2 CRYPTO=windows MSRPC=1 $PROGRAM_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $PROGRAM_NAME
+ exit $?
+fi
+
+export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--nxcompat,--dynamicbase,--tsaware,--high-entropy-va,--disable-long-section-names -fwhole-program"
+export PLATFORMFLAGS="-march=nocona -mtune=generic -pipe -flto=jobserver"
+
+make $MAKEFLAGS MSRPC=1 CRYPTO=windows $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# mips1el uclibc with old tomato toolchain gcc 3.2.3 with Broadcom extensions uClibc 0.9.19
+export CLIENT_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcs-mips1el-tomato-uclibc
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsd-mips1el-tomato-uclibc
+export MULTI_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsdmulti-mips1el-tomato-uclibc
+export CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
+export CFLAGS="-DNO_BUILTIN -DNO_LIMIT -pipe -fno-common -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
+export PLATFORMFLAGS=""
+export LDFLAGS="-fwhole-program -Wl,-z,norelro"
+export THREADS=0
+#export TERMINAL_WIDTH=80
+
+make $MAKEFLAGS NO_DNS=1 SAFE_MODE=1
if [ $? != 0 ]; then
echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
exit $?
fi
-make $MAKEFLAGS MSRPC=1 $MULTI_NAME
+rm -f vlmcs.o vlmcsd.o vlmcsdmulti.o
+
+make NO_DNS=1 SAFE_MODE=1 $REUSEOBJFLAGS $MULTI_NAME
if [ $? != 0 ]; then
echo Error creating $MULTI_NAME
exit $?
fi
+export CLIENT_NAME=binaries/Linux/mips/little-endian/static/vlmcs-mips1el-tomato-uclibc-static
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/static/vlmcsd-mips1el-tomato-uclibc-static
+export MULTI_NAME=binaries/Linux/mips/little-endian/static/vlmcsdmulti-mips1el-tomato-uclibc-static
+export LDFLAGS="$LDFLAGS -static"
+
+make NO_DNS=1 SAFE_MODE=1 $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+rm -f vlmcs.o vlmcsd.o vlmcsdmulti.o
+
+make NO_DNS=1 SAFE_MODE=1 $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
@@ -539,40 +616,6 @@ fi
-
-# mips1el uclibc with old tomato toolchain gcc 3.2.3 with Broadcom extensions uClibc 0.9.19
-export CLIENT_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcs-mips1el-tomato-uclibc
-export PROGRAM_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsd-mips1el-tomato-uclibc
-export MULTI_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsdmulti-mips1el-tomato-uclibc
-export CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
-export CFLAGS="-DNO_BUILTIN -pipe -fno-common -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
-export PLATFORMFLAGS=""
-export LDFLAGS="-pipe -Wl,-z,norelro"
-export THREADS=0
-#export TERMINAL_WIDTH=80
-
-make NO_DNS=1 CAT=2 $MAKEFLAGS $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
-
-if [ $? != 0 ]; then
- echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
- exit $?
-fi
-
-export CLIENT_NAME=binaries/Linux/mips/little-endian/static/vlmcs-mips1el-tomato-uclibc-static
-export PROGRAM_NAME=binaries/Linux/mips/little-endian/static/vlmcsd-mips1el-tomato-uclibc-static
-export MULTI_NAME=binaries/Linux/mips/little-endian/static/vlmcsdmulti-mips1el-tomato-uclibc-static
-export LDFLAGS="$LDFLAGS -static"
-
-make NO_DNS=1 $REUSEOBJFLAGS $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME CAT=2
-
-if [ $? != 0 ]; then
- echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
- exit $?
-fi
-
-
-
-
#Android gcc 4.8 with API Level 3 (Android 1.5 cupcake) armv7
export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android15-armv7
@@ -1616,7 +1659,7 @@ export PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x32-glibc
export CC=gcc
export CFLAGS="$SMALLCC"
export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mx32 -march=nocona -mtune=generic"
-export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export LDFLAGS="-fuse-ld=gold $SMALLLD -Wl,--hash-style=gnu"
export THREADS=0
export NOPROCFS=0
export AUXV=1
@@ -1646,7 +1689,7 @@ export PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x32-glibc-threads
export CC=gcc
export CFLAGS="$SMALLCC"
export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mx32 -march=nocona -mtune=generic"
-export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -lpthread"
+export LDFLAGS="-fuse-ld=gold $SMALLLD -Wl,--hash-style=gnu -lpthread"
export THREADS=1
export NOPROCFS=0
export AUXV=1
@@ -2121,10 +2164,19 @@ export LDFLAGS="-Wl,-z,norelro -fwhole-program"
export THREADS=0
export NOPROCFS=1
-make $MAKEFLAGS $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME CAT=2
+make $MAKEFLAGS SAFE_MODE=1
if [ $? != 0 ]; then
- echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
+
+make $REUSEOBJFLAGS SAFE_MODE=1 $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
exit $?
fi
@@ -2133,10 +2185,19 @@ export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
export LDFLAGS="-Wl,-z,norelro -fwhole-program -static"
-make $REUSEOBJFLAGS $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME CAT=2
+make $REUSEOBJFLAGS SAFE_MODE=1 $MULTI_NAME
if [ $? != 0 ]; then
- echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
+
+make $REUSEOBJFLAGS SAFE_MODE=1
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
exit $?
fi
@@ -2226,10 +2287,19 @@ export THREADS=0
export CRYPTO=internal
export NOPROCFS=1
-make $MAKEFLAGS CAT=2 $CLIENT_NAME $MULTI_NAME $PROGRAM_NAME
+make $MAKEFLAGS SAFE_MODE=1
if [ $? != 0 ]; then
- echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm vlmcsd.o vlmcs.o vlmcsdmulti.o
+
+make $REUSEOBJFLAGS SAFE_MODE=1 $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
exit $?
fi
@@ -2238,10 +2308,19 @@ export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
export LDFLAGS="-Wl,-z,norelro -fwhole-program -static"
-make $REUSEOBJFLAGS CAT=2 $CLIENT_NAME $MULTI_NAME $PROGRAM_NAME
+make $REUSEOBJFLAGS SAFE_MODE=1 $MULTI_NAME
if [ $? != 0 ]; then
- echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+rm vlmcsd.o vlmcs.o vlmcsdmulti.o
+
+make $REUSEOBJFLAGS SAFE_MODE=1
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
exit $?
fi
@@ -2315,32 +2394,6 @@ fi
-# Linux PowerPC glibc with SSL support and Dreambox 500 toolchain
-INSTALLDIR=binaries/Linux/ppc/big-endian/glibc/
-SUFFIX=-ppc-glibc-openssl0.9.8-soft-EXPERIMENTAL
-export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
-export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
-export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
-export CC=/opt/simplebuild/toolchains/powerpc/bin/powerpc-linux-gcc
-export PLATFORMFLAGS="-pipe"
-export FEATURES=full
-export CFLAGS="-fno-common -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
-export LDFLAGS="-Wl,--no-gc-sections -Wl,-z,norelro"
-export THREADS=0
-export CRYPTO=internal
-
-make NO_DNS=1 $MAKEFLAGS CAT=2 $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
-
-if [ $? != 0 ]; then
- echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
- exit $?
-fi
-
-
-
-
-
-
#Linux PowerPC uclibc OpenWRT toolchain
INSTALLDIR=binaries/Linux/ppc/big-endian/
SUFFIX=-ppc-uclibc
@@ -2531,6 +2584,30 @@ fi
+#Fritzbox 7370 (mips32r2 big-endian) device specific with simple sockets and some features disabled, May or may not run on other devices
+INSTALLDIR=binaries/Linux/mips/big-endian/uclibc/
+SUFFIX=-mips16-Fritzbox-33xx-73xx-74xx-63xx-64xx-uclibc-simple
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/simplebuild/toolchains/fritz73xxOS62/bin/mips-linux-cc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=24kc -mtune=24kc -mips16 -mdsp"
+export FEATURES=full
+export CFLAGS="$SMALLCC -DNO_USER_SWITCH -DSIMPLE_SOCKETS -DNO_PID_FILE -DNO_USER_SWITCH -DNO_USER_SWITCH"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make NOLRESOLV=1 $MAKEFLAGS $PROGRAM_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $PROGRAM_NAME
+ exit $?
+fi
+
+
+
+
#Fritzbox 7370 (mips32r2 big-endian) device specific inetd start only, May or may not run on other devices
INSTALLDIR=binaries/Linux/mips/big-endian/uclibc/
SUFFIX=-mips16-Fritzbox-33xx-73xx-74xx-63xx-64xx-uclibc-inetd
@@ -3132,7 +3209,7 @@ fi
#Linux Sparc32v7 glibc
-INSTALLDIR=binaries/Linux/sparc32/glibc/
+INSTALLDIR=binaries/Linux/sparc/glibc/
SUFFIX=-sparc32v7-glibc
export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
@@ -3141,7 +3218,7 @@ export CC=/opt/toolchains/sparc32-glibc-gcc-4.7.4/bin/sparc-buildroot-linux-gnu-
export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mcpu=v7"
export FEATURES=full
export CFLAGS="$SMALLCC"
-export LDFLAGS="$SMALLLD -lpthread"
+export LDFLAGS="$SMALLLD"
export THREADS=0
export CRYPTO=internal
@@ -3330,7 +3407,7 @@ export LDFLAGS="-fwhole-program"
export THREADS=0
export CRYPTO=internal
-make $MAKEFLAGS CAT=2 $PROGRAM_NAME $MULTI_NAME $CLIENT_NAME
+make $MAKEFLAGS CAT=2 SAFE_MODE=1 $PROGRAM_NAME $MULTI_NAME $CLIENT_NAME
if [ $? != 0 ]; then
echo Error creating $PROGRAM_NAME, $MULTI_NAME and/or $CLIENT_NAME
@@ -3342,7 +3419,7 @@ export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
export LDFLAGS="-fwhole-program -static"
-make $REUSEOBJFLAGS CAT=2 $PROGRAM_NAME $MULTI_NAME $CLIENT_NAME
+make $REUSEOBJFLAGS CAT=2 SAFE_MODE=1 $PROGRAM_NAME $MULTI_NAME $CLIENT_NAME
if [ $? != 0 ]; then
echo Error creating $PROGRAM_NAME, $MULTI_NAME and/or $CLIENT_NAME
@@ -3456,7 +3533,7 @@ export CFLAGS="$SMALLCC"
export LDFLAGS="-Wl,-z,norelo"
export THREADS=0
-make $MAKEFLAGS CAT=2 $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+make $MAKEFLAGS SAFE_MODE=1 CAT=2 $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
if [ $? != 0 ]; then
echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
@@ -3468,7 +3545,7 @@ export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
export LDFLAGS="-Wl,-z,norelo -static"
-make $REUSEOBJFLAGS CAT=2 $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+make $REUSEOBJFLAGS SAFE_MODE=1 CAT=2 $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
if [ $? != 0 ]; then
echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
@@ -3478,9 +3555,9 @@ fi
# Strip off unnecessary stuff from binaries
-find binaries -xdev -name 'vlmcs*' -exec /opt/toolchains/mips32el-mips16-glibc-2.18/usr/bin/mipsel-linux-strip -s --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag {} \; 2>/dev/null
-find binaries -xdev -name 'vlmcs*' -exec strip -s --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag {} \; 2>/dev/null
-find binaries -xdev -name 'vlmcs*' -exec sstrip -z {} \; 2>/dev/null
+#find binaries -xdev -name 'vlmcs*' -exec /opt/toolchains/mips32el-mips16-glibc-2.18/usr/bin/mipsel-linux-strip -s --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag {} \; 2>/dev/null
+#find binaries -xdev -name 'vlmcs*' -exec strip -s --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag {} \; 2>/dev/null
+find binaries -xdev -name 'vlmcs*' ! -name '*-NetBSD-*' ! -name '*-Windows-*' ! -name '*-cygwin-*' ! -name '*-MacOSX-*' ! -name '*-iOS-*' -exec sstrip -z {} \;
make alldocs
diff --git a/make_lxss b/make_lxss
new file mode 100755
index 0000000..e4d0dfc
--- /dev/null
+++ b/make_lxss
@@ -0,0 +1,3507 @@
+#!/bin/bash
+
+#export VLMCSD_VERSION="svn`svnversion | sed -e 's/:.*//; s/[^0-9]*$//; s/^$/0/'`"
+
+export VERBOSE=3
+export DNS_PARSER=internal
+
+MAKEFLAGS="-j`nproc` -B"
+REUSEOBJFLAGS="-j"
+SMALLCC="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
+SMALLLD="-pipe -Wl,--hash-style=sysv -Wl,-z,norelro -Wl,--build-id=none"
+SMALL="$SMALLCC $SMALLLD"
+
+
+rm -f vlmcs vlmcsdmulti vlmcsd 2>/dev/null
+rm -fr binaries
+
+mkdir -p binaries/Linux/intel/glibc
+mkdir -p binaries/Linux/intel/uclibc
+mkdir -p binaries/Linux/intel/static
+mkdir -p binaries/Linux/intel/musl
+
+mkdir -p binaries/Linux/sparc32/glibc
+mkdir -p binaries/Linux/s390/glibc
+
+mkdir -p binaries/Android/arm/bionic
+mkdir -p binaries/Android/arm/static
+mkdir -p binaries/Android/intel/bionic
+mkdir -p binaries/Android/intel/static
+mkdir -p binaries/Android/mips/bionic
+mkdir -p binaries/Android/mips/static
+
+mkdir -p binaries/Linux/arm/little-endian/glibc
+mkdir -p binaries/Linux/arm/little-endian/musl
+mkdir -p binaries/Linux/arm/little-endian/uclibc
+mkdir -p binaries/Linux/arm/little-endian/static
+mkdir -p binaries/Linux/arm/big-endian/uclibc
+mkdir -p binaries/Linux/arm/big-endian/static
+
+mkdir -p binaries/Linux/mips/little-endian/glibc
+mkdir -p binaries/Linux/mips/little-endian/uclibc
+mkdir -p binaries/Linux/mips/little-endian/static
+mkdir -p binaries/Linux/mips/little-endian/musl
+mkdir -p binaries/Linux/mips/big-endian/uclibc
+mkdir -p binaries/Linux/mips/big-endian/static
+mkdir -p binaries/Linux/mips/big-endian/glibc
+mkdir -p binaries/Linux/mips/big-endian/musl
+
+mkdir -p binaries/Linux/ppc/little-endian/glibc
+mkdir -p binaries/Linux/ppc/big-endian/glibc
+mkdir -p binaries/Linux/ppc/big-endian/uclibc
+mkdir -p binaries/Linux/ppc/big-endian/static
+
+mkdir -p binaries/MacOSX/intel
+mkdir -p binaries/MacOSX/ppc
+mkdir -p binaries/iOS/arm
+
+mkdir -p binaries/FreeBSD/intel
+mkdir -p binaries/NetBSD/intel
+mkdir -p binaries/OpenBSD/intel
+mkdir -p binaries/DragonFly/intel
+mkdir -p binaries/Solaris/intel
+mkdir -p binaries/Windows/intel
+mkdir -p binaries/Minix/intel
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+export STAGING_DIR=.
+
+# Windows 32-bit using MingW32-w64 toolchain on Ubuntu Linux
+export CLIENT_NAME=binaries/Windows/intel/vlmcs-Windows-x86.exe
+export PROGRAM_NAME=binaries/Windows/intel/vlmcsd-Windows-x86.exe
+export MULTI_NAME=binaries/Windows/intel/vlmcsdmulti-Windows-x86.exe
+export DLL_NAME=binaries/Windows/intel/libkms32.dll
+export THREADS=1
+export CFLAGS="$SMALLCC"
+export CC=i686-w64-mingw32-gcc
+export PLATFORMFLAGS="-march=i686 -mtune=generic -fwhole-program -pipe"
+export LDFLAGS="-lws2_32 -Wl,--gc-sections,--force-exe-suffix,--large-address-aware,--nxcompat,--dynamicbase,--tsaware"
+export FEATURES=full
+
+make $MAKEFLAGS CAT=2 all $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export CFLAGS="$CFLAGS -flto=jobserver -fvisibility=hidden"
+export LDFLAGS="$LDFLAGS -static-libgcc"
+
+make $MAKEFLAGS FEATURES=minimum $DLL_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $DLL_NAME
+ exit $?
+fi
+
+
+
+# Windows 32-bit using MingW32-w64 toolchain on Ubuntu Linux using MS RPC
+export CLIENT_NAME=binaries/Windows/intel/vlmcs-Windows-msrpc-x86.exe
+export PROGRAM_NAME=binaries/Windows/intel/vlmcsd-Windows-msrpc-x86.exe
+export MULTI_NAME=binaries/Windows/intel/vlmcsdmulti-Windows-msrpc-x86.exe
+export THREADS=1
+export CFLAGS="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fmerge-all-constants -Wno-unused-variable -Wno-missing-braces"
+export CC=i686-w64-mingw32-gcc
+export PLATFORMFLAGS="-march=i686 -mtune=generic -pipe"
+export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--large-address-aware,--nxcompat,--dynamicbase,--tsaware -fwhole-program"
+export FEATURES=full
+
+make $MAKEFLAGS CAT=2 MSRPC=1 all
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+make $MAKEFLAGS MSRPC=1 $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+# Windows 64-bit using MingW32-w64 toolchain on Ubuntu Linux
+export CLIENT_NAME=binaries/Windows/intel/vlmcs-Windows-x64.exe
+export PROGRAM_NAME=binaries/Windows/intel/vlmcsd-Windows-x64.exe
+export MULTI_NAME=binaries/Windows/intel/vlmcsdmulti-Windows-x64.exe
+export DLL_NAME=binaries/Windows/intel/libkms64.dll
+export THREADS=1
+export CFLAGS="$SMALLCC"
+export CC=x86_64-w64-mingw32-gcc
+export PLATFORMFLAGS="-march=nocona -mtune=generic -fwhole-program -pipe"
+export LDFLAGS="-lws2_32 -Wl,--gc-sections,--force-exe-suffix,--nxcompat,--dynamicbase,--tsaware"
+
+make $MAKEFLAGS CAT=2 all $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export CFLAGS="$CFLAGS -flto=jobserver -fvisibility=hidden"
+export LDFLAGS="$LDFLAGS -static-libgcc"
+
+make $MAKEFLAGS FEATURES=minimum $DLL_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $DLL_NAME
+ exit $?
+fi
+
+
+
+
+# Windows 64-bit using MingW32-w64 toolchain on Ubuntu Linux using MS RPC
+export CLIENT_NAME=binaries/Windows/intel/vlmcs-Windows-msrpc-x64.exe
+export PROGRAM_NAME=binaries/Windows/intel/vlmcsd-Windows-msrpc-x64.exe
+export MULTI_NAME=binaries/Windows/intel/vlmcsdmulti-Windows-msrpc-x64.exe
+export THREADS=1
+export CFLAGS="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fmerge-all-constants -Wno-unused-variable -Wno-missing-braces"
+export CC=x86_64-w64-mingw32-gcc
+export PLATFORMFLAGS="-march=nocona -mtune=generic -pipe"
+export LDFLAGS="-Wl,--gc-sections,--force-exe-suffix,--nxcompat,--dynamicbase,--tsaware -fwhole-program"
+
+make $MAKEFLAGS CAT=2 MSRPC=1 all
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+make $MAKEFLAGS MSRPC=1 $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux mips32el with uClibc 0.9.33.2 using gcc 4.9 from OpenWRT toolchain
+export CLIENT_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcs-mips32el-openwrt-uclib
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsd-mips32el-openwrt-uclibc
+export CC=/opt/toolchains/mipsel-openwrt-linux-uclibc/toolchain-mipsel_mips32_gcc-4.9-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-gcc
+export CFLAGS="$SMALLCC -DNO_LIMIT"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export CLIENT_NAME=binaries/Linux/mips/little-endian/static/vlmcs-mips32el-openwrt-uclib-static
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/static/vlmcsd-mips32el-openwrt-uclibc-static
+export MULTI_NAME=binaries/Linux/mips/little-endian/static/vlmcsdmulti-mips32el-openwrt-uclibc-static
+export LDFLAGS="$LDFLAGS -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsdmulti-mips32el-openwrt-uclibc
+export LDFLAGS="$SMALLLD"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux mips16el with uClibc 0.9.33.2 using gcc 4.9 from OpenWRT toolchain with statically linked libgcc for Asus routers, e.g. Asus RT-N66U
+export CLIENT_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcs-mips16el-asus-rt-n66u-uclibc
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsd-mips16el-asus-rt-n66u-uclibc
+export CC=/opt/toolchains/mipsel-openwrt-linux-uclibc/toolchain-mipsel_mips32_gcc-4.9-linaro_uClibc-0.9.33.2/bin/mipsel-openwrt-linux-gcc
+export CFLAGS="$SMALLCC -static-libgcc -DNO_LIMIT"
+export PLATFORMFLAGS="-mips32 -mips16 -flto=jobserver -fwhole-program"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export CLIENT_NAME=binaries/Linux/mips/little-endian/static/vlmcs-mips16el-asus-rt-n66u-uclibc-static
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/static/vlmcsd-mips16el-asus-rt-n66u-uclibc-static
+export MULTI_NAME=binaries/Linux/mips/little-endian/static/vlmcsdmulti-mips16el-asus-rt-n66u-uclibc-static
+export LDFLAGS="$LDFLAGS -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsdmulti-mips16el-asus-rt-n66u-uclibc
+export LDFLAGS="$SMALLLD"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+
+
+# Linux mips16el with uClibc 0.9.33.2 using gcc 4.8 from OpenWRT toolchain
+export CLIENT_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcs-mips16el-openwrt-uclibc
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsd-mips16el-openwrt-uclibc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips16"
+export LDFLAGS="$SMALLLD"
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export CLIENT_NAME=binaries/Linux/mips/little-endian/static/vlmcs-mips16el-openwrt-uclib-static
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/static/vlmcsd-mips16el-openwrt-uclibc-static
+export MULTI_NAME=binaries/Linux/mips/little-endian/static/vlmcsdmulti-mips16el-openwrt-uclibc-static
+export LDFLAGS="$LDFLAGS -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsdmulti-mips16el-openwrt-uclibc
+export LDFLAGS="$SMALLLD"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux mips16el eglibc 2.19 using gcc 4.8 from OpenWRT toolchain
+export CLIENT_NAME=binaries/Linux/mips/little-endian/glibc/vlmcs-mips16el-openwrt-glibc
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/glibc/vlmcsd-mips16el-openwrt-glibc
+export MULTI_NAME=binaries/Linux/mips/little-endian/glibc/vlmcsdmulti-mips16el-openwrt-glibc
+export CC=/opt/toolchains/mipsel_74kc+dsp2_gcc-4.9-linaro_eglibc-2.19-mips16/bin/mipsel-openwrt-linux-gnu-gcc-4.9.2
+#export CC=~/openwrt/staging_dir/toolchain-mipsel_mips32_gcc-4.8-linaro_eglibc-2.19/bin/mipsel-openwrt-linux-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=mips32 -mips16"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# PowerPC 64-bit big-endian glibc.
+export CLIENT_NAME=binaries/Linux/ppc/big-endian/glibc/vlmcs-ppc64-glibc
+export PROGRAM_NAME=binaries/Linux/ppc/big-endian/glibc/vlmcsd-ppc64-glibc
+export MULTI_NAME=binaries/Linux/ppc/big-endian/glibc/vlmcsdmulti-ppc64-glibc
+export CC=/opt/toolchains/ppc64-glibc2.19-gcc-4.9.1/bin/powerpc64-linux-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# PowerPC 64-bit little-endian glibc.
+export CLIENT_NAME=binaries/Linux/ppc/little-endian/glibc/vlmcs-ppc64el-glibc
+export PROGRAM_NAME=binaries/Linux/ppc/little-endian/glibc/vlmcsd-ppc64el-glibc
+export MULTI_NAME=binaries/Linux/ppc/little-endian/glibc/vlmcsdmulti-ppc64el-glibc
+export CC=/opt/toolchains/ppc64el-glibc2.20-gcc-4.9.1/bin/powerpc64le-linux-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+
+make DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# PowerPC glibc. Compiles with gcc 4.8 from OpenWRT toolchain but uses libs from an old DM500 toolchain to be compatible with glibc 2.3
+export CLIENT_NAME=binaries/Linux/ppc/big-endian/glibc/vlmcs-ppc-glibc
+export PROGRAM_NAME=binaries/Linux/ppc/big-endian/glibc/vlmcsd-ppc-glibc
+export MULTI_NAME=binaries/Linux/ppc/big-endian/glibc/vlmcsdmulti-ppc-glibc
+export CC=~/openwrt/staging_dir/toolchain-powerpc_405_gcc-4.8-linaro_eglibc-2.19/bin/powerpc-openwrt-linux-gnu-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program --sysroot=/opt/simplebuild/toolchains/powerpc -L/opt/simplebuild/toolchains/powerpc/lib -L/opt/simplebuild/toolchains/powerpc/usr/lib"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Mips 32 glibc compiled with gcc 4.9.2 from OpenWRT toolchain
+export CLIENT_NAME=binaries/Linux/mips/big-endian/glibc/vlmcs-mips32-openwrt-glibc
+export PROGRAM_NAME=binaries/Linux/mips/big-endian/glibc/vlmcsd-mips32-openwrt-glibc
+export MULTI_NAME=binaries/Linux/mips/big-endian/glibc/vlmcsdmulti-mips32-openwrt-glibc
+export CC=/opt/toolchains/mips_34kc_gcc-4.9-linaro_eglibc-2.19-mips16/bin/mips-openwrt-linux-gcc
+#export CC=~/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_eglibc-2.19/bin/mips-openwrt-linux-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips32"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+
+# Mips 32 glibc compiled with gcc 4.9.2 from OpenWRT toolchain
+export CLIENT_NAME=binaries/Linux/mips/big-endian/glibc/vlmcs-mips16-openwrt-glibc
+export PROGRAM_NAME=binaries/Linux/mips/big-endian/glibc/vlmcsd-mips16-openwrt-glibc
+export MULTI_NAME=binaries/Linux/mips/big-endian/glibc/vlmcsdmulti-mips16-openwrt-glibc
+export CC=/opt/toolchains/mips_34kc_gcc-4.9-linaro_eglibc-2.19-mips16/bin/mips-openwrt-linux-gcc
+#export CC=~/openwrt/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_eglibc-2.19/bin/mips-openwrt-linux-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips32 -mips16"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+
+# mips32el glibc 2.19 compiled with gcc 4.8 from OpenWRT toolchain
+export CLIENT_NAME=binaries/Linux/mips/little-endian/glibc/vlmcs-mips32el-openwrt-glibc
+export PROGRAM_NAME=binaries/Linux/mips/little-endian/glibc/vlmcsd-mips32el-openwrt-glibc
+export MULTI_NAME=binaries/Linux/mips/little-endian/glibc/vlmcsdmulti-mips32el-openwrt-glibc
+export CC=/opt/toolchains/mipsel_74kc+dsp2_gcc-4.9-linaro_eglibc-2.19-mips16/bin/mipsel-openwrt-linux-gnu-gcc-4.9.2
+#export CC=~/openwrt/staging_dir/toolchain-mipsel_mips32_gcc-4.8-linaro_eglibc-2.19/bin/mipsel-openwrt-linux-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips32"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+## mips1el uclibc with old tomato toolchain gcc 3.2.3 with Broadcom extensions uClibc 0.9.19
+#export CLIENT_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcs-mips1el-tomato-uclibc
+#export PROGRAM_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsd-mips1el-tomato-uclibc
+#export MULTI_NAME=binaries/Linux/mips/little-endian/uclibc/vlmcsdmulti-mips1el-tomato-uclibc
+#export CC=/opt/brcm/hndtools-mipsel-uclibc/bin/mipsel-uclibc-gcc
+#export CFLAGS="-DNO_BUILTIN -pipe -fno-common -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
+#export PLATFORMFLAGS=""
+#export LDFLAGS="-pipe -Wl,-z,norelro"
+#export THREADS=0
+##export TERMINAL_WIDTH=80
+#
+#make NO_DNS=1 CAT=2 $MAKEFLAGS $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#export CLIENT_NAME=binaries/Linux/mips/little-endian/static/vlmcs-mips1el-tomato-uclibc-static
+#export PROGRAM_NAME=binaries/Linux/mips/little-endian/static/vlmcsd-mips1el-tomato-uclibc-static
+#export MULTI_NAME=binaries/Linux/mips/little-endian/static/vlmcsdmulti-mips1el-tomato-uclibc-static
+#export LDFLAGS="$LDFLAGS -static"
+#
+#make NO_DNS=1 $REUSEOBJFLAGS $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME CAT=2
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+
+
+
+
+#Android gcc 4.8 with API Level 3 (Android 1.5 cupcake) armv7
+
+export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android15-armv7
+export PROGRAM_NAME=binaries/Android/arm/bionic/vlmcsd-android15-armv7
+export CC=/opt/toolchains/armelv7-android-3/bin/arm-linux-androideabi-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-fuse-ld=bfd -flto=jobserver -fwhole-program -march=armv7 -mthumb"
+export THREADS=0
+export LDFLAGS="$SMALLLD"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+#export CLIENT_NAME=binaries/Android/arm/static/vlmcs-android15-armv7-static
+#export PROGRAM_NAME=binaries/Android/arm/static/vlmcsd-android15-armv7-static
+#export MULTI_NAME=binaries/Android/arm/static/vlmcsdmulti-android15-armv7-static
+#export LDFLAGS="$LDFLAGS -static"
+#
+#make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+export LDFLAGS="$SMALLLD"
+export MULTI_NAME=binaries/Android/arm/bionic/vlmcsdmulti-android15-armv7
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Android gcc 4.8 with API Level 3 (Android 1.5 cupcake) armv5
+
+export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android15-armv5
+export PROGRAM_NAME=binaries/Android/arm/bionic/vlmcsd-android15-armv5
+export CC=/opt/toolchains/armelv7-android-3/bin/arm-linux-androideabi-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-fuse-ld=bfd -flto=jobserver -fwhole-program -march=armv5te -mthumb"
+export THREADS=0
+export LDFLAGS="$SMALLLD"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+#export CLIENT_NAME=binaries/Android/arm/static/vlmcs-android15-armv5-static
+#export PROGRAM_NAME=binaries/Android/arm/static/vlmcsd-android15-armv5-static
+#export MULTI_NAME=binaries/Android/arm/static/vlmcsdmulti-android15-armv5-static
+#export LDFLAGS="$LDFLAGS -static"
+
+#make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+export LDFLAGS="$SMALLLD"
+export MULTI_NAME=binaries/Android/arm/bionic/vlmcsdmulti-android15-armv5
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+#Android gcc 4.8 with API Level 16 (Android 4.1 Jelly Bean) armv7
+
+export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android41-armv7
+export PROGRAM_NAME=binaries/Android/arm/bionic/vlmcsd-android41-armv7
+export MULTI_NAME=binaries/Android/arm/bionic/vlmcsdmulti-android41-armv7
+export CC=/opt/toolchains/armelv7-android-16/bin/arm-linux-androideabi-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv7 -mthumb -fPIE -pie"
+export THREADS=0
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+##Android gcc 4.8 with API Level 21 (Android 5.0 Lollipop) armv7
+#
+#export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android50-armv7
+#export PROGRAM_NAME=binaries/Android/arm/bionic/vlmcsd-android50-armv7
+#export MULTI_NAME=binaries/Android/arm/bionic/vlmcsdmulti-android50-armv7
+#export CC=/opt/toolchains/armelv7-android-21/bin/arm-linux-androideabi-gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv7 -mthumb -fPIE -pie"
+#export THREADS=0
+#export LDFLAGS="$SMALLLD"
+#
+#make NOLPTHREAD=1 $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLPTHREAD=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#
+#
+#
+#
+#Android gcc 4.9 with API Level 21 (Android 5.0 Lollipop) arm64el
+
+export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android50-arm64v8
+export PROGRAM_NAME=binaries/Android/arm/bionic/vlmcsd-android50-arm64v8
+export MULTI_NAME=binaries/Android/arm/bionic/vlmcsdmulti-android50-arm64v8
+export CC=/opt/toolchains/arm64el-android-21/bin/aarch64-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mtune=generic -mfix-cortex-a53-835769 -march=armv8-a -fPIE -pie"
+export THREADS=0
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 NO_DNS=0 $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 NO_DNS=0 $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Android gcc 4.9 with API Level 21 (Android 5.0 Lollipop) arm64el STATIC
+
+export CLIENT_NAME=binaries/Android/arm/static/vlmcs-android50-arm64v8-static
+export PROGRAM_NAME=binaries/Android/arm/static/vlmcsd-android50-arm64v8-static
+export MULTI_NAME=binaries/Android/arm/static/vlmcsdmulti-android50-arm64v8-static
+export CC=/opt/toolchains/arm64el-android-21/bin/aarch64-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mtune=generic -mfix-cortex-a53-835769 -march=armv8-a"
+export THREADS=0
+export LDFLAGS="$SMALLLD -static -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Android gcc 4.8 with API Level 9 (Android 2.3 Gingerbread) x86
+
+export CLIENT_NAME=binaries/Android/intel/bionic/vlmcs-android23-x86
+export PROGRAM_NAME=binaries/Android/intel/bionic/vlmcsd-android23-x86
+export CC=/opt/toolchains/x86-android-9/bin/i686-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=atom -m32"
+export THREADS=1
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export CLIENT_NAME=binaries/Android/intel/static/vlmcs-android23-x86-static
+export PROGRAM_NAME=binaries/Android/intel/static/vlmcsd-android23-x86-static
+export MULTI_NAME=binaries/Android/intel/static/vlmcsdmulti-android23-x86-static
+export LDFLAGS="$LDFLAGS -static"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+export MULTI_NAME=binaries/Android/intel/bionic/vlmcsdmulti-android23-x86
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Android gcc 4.8 with API Level 16 (Android 4.1 Jelly Bean) x86
+
+export CLIENT_NAME=binaries/Android/intel/bionic/vlmcs-android41-x86
+export PROGRAM_NAME=binaries/Android/intel/bionic/vlmcsd-android41-x86
+export MULTI_NAME=binaries/Android/intel/bionic/vlmcsdmulti-android41-x86
+export CC=/opt/toolchains/x86-android-16/bin/i686-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=atom -m32 -fPIE -pie"
+export THREADS=1
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+##Android gcc 4.8 with API Level 21 (Android 5.0 Lollipop) x86
+#
+#export CLIENT_NAME=binaries/Android/intel/bionic/vlmcs-android50-x86
+#export PROGRAM_NAME=binaries/Android/intel/bionic/vlmcsd-android50-x86
+#export MULTI_NAME=binaries/Android/intel/bionic/vlmcsdmulti-android50-x86
+#export CC=/opt/toolchains/x86-android-21/bin/i686-linux-android-gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=atom -m32 -fPIE -pie"
+#export THREADS=1
+#export LDFLAGS="$SMALLLD"
+#
+#make NOLPTHREAD=1 $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLPTHREAD=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+
+
+
+#Android gcc 4.9 with API Level 21 (Android 5.0 Lollipop) x64
+
+export CLIENT_NAME=binaries/Android/intel/bionic/vlmcs-android50-x64
+export PROGRAM_NAME=binaries/Android/intel/bionic/vlmcsd-android50-x64
+export MULTI_NAME=binaries/Android/intel/bionic/vlmcsdmulti-android50-x64
+export CC=/opt/toolchains/x86_64-android-21/bin/x86_64-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=atom -m64 -fPIE -pie"
+export THREADS=0
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 NO_DNS=0 $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 NO_DNS=0 $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Android gcc 4.9 with API Level 21 (Android 5.0 Lollipop) x64 STATIC
+
+export CLIENT_NAME=binaries/Android/intel/static/vlmcs-android50-x64-static
+export PROGRAM_NAME=binaries/Android/intel/static/vlmcsd-android50-x64-static
+export MULTI_NAME=binaries/Android/intel/static/vlmcsdmulti-android50-x64-static
+export CC=/opt/toolchains/x86_64-android-21/bin/x86_64-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=nocona -m64"
+export THREADS=0
+export LDFLAGS="$SMALLLD -static -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+
+#Android gcc 4.8 with API Level 9 (Android 2.3 Gingerbread) mips32el
+
+export CLIENT_NAME=binaries/Android/mips/bionic/vlmcs-android23-mips32el
+export PROGRAM_NAME=binaries/Android/mips/bionic/vlmcsd-android23-mips32el
+export CC=/opt/toolchains/mipsel-android-9/bin/mipsel-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+export THREADS=1
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export CLIENT_NAME=binaries/Android/mips/static/vlmcs-android23-mips32el-static
+export PROGRAM_NAME=binaries/Android/mips/static/vlmcsd-android23-mips32el-static
+export MULTI_NAME=binaries/Android/mips/static/vlmcsdmulti-android23-mips32el-static
+export LDFLAGS="$LDFLAGS -static -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+export MULTI_NAME=binaries/Android/mips/bionic/vlmcsdmulti-android23-mips32el
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+
+#Android gcc 4.8 with API Level 16 (Android 4.1 Jelly Bean) mips32el
+
+export CLIENT_NAME=binaries/Android/mips/bionic/vlmcs-android41-mips32el
+export PROGRAM_NAME=binaries/Android/mips/bionic/vlmcsd-android41-mips32el
+export MULTI_NAME=binaries/Android/mips/bionic/vlmcsdmulti-android41-mips32el
+export CC=/opt/toolchains/mipsel-android-16/bin/mipsel-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -fPIE -pie"
+export THREADS=1
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+
+##Android gcc 4.8 with API Level 21 (Android 5.0 Lollipop) mips32el
+#
+#export CLIENT_NAME=binaries/Android/mips/bionic/vlmcs-android50-mips32el
+#export PROGRAM_NAME=binaries/Android/mips/bionic/vlmcsd-android50-mips32el
+#export MULTI_NAME=binaries/Android/mips/bionic/vlmcsdmulti-android50-mips32el
+#export CC=/opt/toolchains/mipsel-android-21/bin/mipsel-linux-android-gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -fPIE -pie"
+#export THREADS=1
+#export LDFLAGS="$SMALLLD"
+#
+#make NOLPTHREAD=1 $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLPTHREAD=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+
+
+
+##Android gcc 4.8 with API Level 9 (Android 2.3 Gingerbread) mips16el
+#
+#export CLIENT_NAME=binaries/Android/mips/bionic/vlmcs-android23-mips16el
+#export PROGRAM_NAME=binaries/Android/mips/bionic/vlmcsd-android23-mips16el
+#export CC=/opt/toolchains/mipsel-android-9/bin/mipsel-linux-android-gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips16"
+#export THREADS=1
+#export LDFLAGS="$SMALLLD"
+#
+#make NOLPTHREAD=1 $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#export CLIENT_NAME=binaries/Android/mips/static/vlmcs-android23-mips16el-static
+#export PROGRAM_NAME=binaries/Android/mips/static/vlmcsd-android23-mips16el-static
+#export MULTI_NAME=binaries/Android/mips/static/vlmcsdmulti-android23-mips16el-static
+#export LDFLAGS="$LDFLAGS -static"
+#
+#make NOLPTHREAD=1 $REUSEOBJFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLPTHREAD=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#export LDFLAGS="$SMALLLD"
+#export MULTI_NAME=binaries/Android/mips/bionic/vlmcsdmulti-android23-mips16el
+#
+#make NOLPTHREAD=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#
+#
+#
+#
+##Android gcc 4.8 with API Level 16 (Android 4.1 Jelly Bean) mips16el
+#
+#export CLIENT_NAME=binaries/Android/mips/bionic/vlmcs-android41-mips16el
+#export PROGRAM_NAME=binaries/Android/mips/bionic/vlmcsd-android41-mips16el
+#export MULTI_NAME=binaries/Android/mips/bionic/vlmcsdmulti-android41-mips16el
+#export CC=/opt/toolchains/mipsel-android-16/bin/mipsel-linux-android-gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -fPIE -pie -mips16"
+#export THREADS=1
+#export LDFLAGS="$SMALLLD"
+#
+#make NOLPTHREAD=1 $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLPTHREAD=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#
+#
+#
+#
+#Android gcc 4.8 with API Level 21 (Android 5.0 Lollipop) mips16el
+#
+#export CLIENT_NAME=binaries/Android/mips/bionic/vlmcs-android50-mips16el
+#export PROGRAM_NAME=binaries/Android/mips/bionic/vlmcsd-android50-mips16el
+#export MULTI_NAME=binaries/Android/mips/bionic/vlmcsdmulti-android50-mips16el
+#export CC=/opt/toolchains/mipsel-android-21/bin/mipsel-linux-android-gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -fPIE -pie -mips16"
+#export THREADS=1
+#export LDFLAGS="$SMALLLD"
+#
+#make NOLPTHREAD=1 $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLPTHREAD=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+
+#Android gcc 4.9 with API Level 21 (Android 5.0 Lollipop) mips64el
+
+export CLIENT_NAME=binaries/Android/mips/bionic/vlmcs-android50-mips64el
+export PROGRAM_NAME=binaries/Android/mips/bionic/vlmcsd-android50-mips64el
+export MULTI_NAME=binaries/Android/mips/bionic/vlmcsdmulti-android50-mips64el
+export CC=/opt/toolchains/mips64el-android-21/bin/mips64el-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -fPIE -pie"
+export THREADS=0
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 NO_DNS=0 $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 NO_DNS=0 $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Android gcc 4.9 with API Level 21 (Android 5.0 Lollipop) mips64el STATIC
+
+export CLIENT_NAME=binaries/Android/mips/static/vlmcs-android50-mips64el-static
+export PROGRAM_NAME=binaries/Android/mips/static/vlmcsd-android50-mips64el-static
+export MULTI_NAME=binaries/Android/mips/static/vlmcsdmulti-android50-mips64el-static
+export CC=/opt/toolchains/mips64el-android-21/bin/mips64el-linux-android-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+export THREADS=0
+export LDFLAGS="$SMALLLD -static -fuse-ld=bfd"
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make NOLPTHREAD=1 NOLRESOLV=1 DNS_PARSER=OS $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+## Android 5.0+ with Ubuntu toolchain
+#export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android5
+#export PROGRAM_NAME=binaries/Android/arm/bionic/vlmcsd-android5
+#export CC=arm-linux-androideabi-gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+#export LDFLAGS="$SMALLLD -pie -fpie"
+#export THREADS=0
+#
+#make $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#
+# Android 5.0+ with Ubuntu toolchain STATIC
+#export CLIENT_NAME=binaries/Android/arm/static/vlmcs-android5-static
+#export PROGRAM_NAME=binaries/Android/arm/static/vlmcsd-android5-static
+#export MULTI_NAME=binaries/Android/arm/static/vlmcsdmulti-android5-static
+#export LDFLAGS="$LDFLAGS -static"
+#
+#make $REUSEOBJFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#export LDFLAGS="$SMALLLD -pie -fpie"
+#export MULTI_NAME=binaries/Android/arm/bionic/vlmcsdmulti-android5
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#
+#
+#
+## Android 5.0+ with Ubuntu toolchain for ARMv7 CPU with thumb2 instruction set
+#export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android5-armv7
+#export PROGRAM_NAME=binaries/Android/arm/bionic/vlmcsd-android5-armv7
+#export CC=arm-linux-androideabi-gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mthumb -march=armv7 -mtune=cortex-a9"
+#export LDFLAGS="$SMALLLD -pie -fpie"
+#export THREADS=0
+#
+#make $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#export CLIENT_NAME=binaries/Android/arm/static/vlmcs-android5-armv7-static
+#export PROGRAM_NAME=binaries/Android/arm/static/vlmcsd-android5-armv7-static
+#export MULTI_NAME=binaries/Android/arm/static/vlmcsdmulti-android5-armv7-static
+#export LDFLAGS="$LDFLAGS -static"
+#
+#make $REUSEOBJFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#export LDFLAGS="$SMALLLD -pie -fpie"
+#export MULTI_NAME=binaries/Android/arm/bionic/vlmcsdmulti-android5-armv7
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+##unset TERMINAL_WIDTH
+#
+#
+#
+#
+#
+# Android with Ubuntu toolchain
+export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android
+export PROGRAM_NAME=binaries/Android/arm/bionic/vlmcsd-android
+export CC=arm-linux-androideabi-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+export THREADS=0
+#
+#make $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#
+# Android with Ubuntu toolchain STATIC
+export CLIENT_NAME=binaries/Android/arm/static/vlmcs-android-static
+export PROGRAM_NAME=binaries/Android/arm/static/vlmcsd-android-static
+export MULTI_NAME=binaries/Android/arm/static/vlmcsdmulti-android-static
+export LDFLAGS="$LDFLAGS -static"
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+#export LDFLAGS="$SMALLLD"
+#export MULTI_NAME=binaries/Android/arm/bionic/vlmcsdmulti-android
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+
+
+
+# Android with Ubuntu toolchain for ARMv7 CPU with thumb2 instruction set
+export CLIENT_NAME=binaries/Android/arm/bionic/vlmcs-android-armv7
+export PROGRAM_NAME=binaries/Android/arm/bionic/vlmcsd-android-armv7
+export CC=arm-linux-androideabi-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mthumb -march=armv7 -mtune=cortex-a9"
+export LDFLAGS="$SMALLLD -fuse-ld=bfd"
+export THREADS=0
+
+#make $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+
+export CLIENT_NAME=binaries/Android/arm/static/vlmcs-android-armv7-static
+export PROGRAM_NAME=binaries/Android/arm/static/vlmcsd-android-armv7-static
+export MULTI_NAME=binaries/Android/arm/static/vlmcsdmulti-android-armv7-static
+export LDFLAGS="$LDFLAGS -static"
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+#export LDFLAGS="$SMALLLD"
+#export MULTI_NAME=binaries/Android/arm/bionic/vlmcsdmulti-android-armv7
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+
+
+
+# Linux x86 glibc
+export MULTI_NAME=binaries/Linux/intel/glibc/vlmcsdmulti-x86-glibc
+export CLIENT_NAME=binaries/Linux/intel/glibc/vlmcs-x86-glibc
+export PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x86-glibc
+export CC=~/openwrt/staging_dir/toolchain-i386_i486_gcc-4.8-linaro_eglibc-2.19/bin/i486-openwrt-linux-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m32 -march=i686 -mtune=generic"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+
+make $MAKEFLAGS binaries/Linux/intel/glibc/vlmcsdmulti-x86-glibc
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+
+
+
+# Linux x86 glibc minimum standalone version
+export PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x86-glibc-minimum
+export CC=~/openwrt/staging_dir/toolchain-i386_i486_gcc-4.8-linaro_eglibc-2.19/bin/i486-openwrt-linux-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m32 -march=i686 -mtune=generic"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+export FEATURES=minimum
+
+make NO_DNS=1 $MAKEFLAGS $PROGRAM_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $PROGRAM_NAME
+ exit $?
+fi
+
+# Linux x86 glibc minimum inetd version
+export PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x86-glibc-minimum-inetd
+export CFLAGS="$CFLAGS -DNO_SOCKETS"
+
+make NO_DNS=1 $MAKEFLAGS $PROGRAM_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $PROGRAM_NAME
+ exit $?
+fi
+
+# Linux x86 glibc threads
+export FEATURES=full
+export THREADS=1
+export PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x86-glibc-threads
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -lpthread"
+export CFLAGS="$SMALLCC"
+
+make $MAKEFLAGS $PROGRAM_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $PROGRAM_NAME
+ exit $?
+fi
+
+
+
+
+# Linux x86 musl
+export FEATURES=full
+export MULTI_NAME=binaries/Linux/intel/static/vlmcsdmulti-x86-musl-static
+export CLIENT_NAME=binaries/Linux/intel/static/vlmcs-x86-musl-static
+export PROGRAM_NAME=binaries/Linux/intel/static/vlmcsd-x86-musl-static
+export CC=/opt/toolchains/i386_i486_gcc-4.9-linaro_musl-1.1.6/bin/i486-openwrt-linux-musl-gcc-4.9.2
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m32 -march=i686 -mtune=generic"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -static"
+export THREADS=0
+export NOPROCFS=0
+export AUXV=1
+
+make $MAKEFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export MULTI_NAME=binaries/Linux/intel/musl/vlmcsdmulti-x86-musl
+
+make $MAKEFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+export LDFLAGS="$LDFLAGS -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export CLIENT_NAME=binaries/Linux/intel/musl/vlmcs-x86-musl
+export PROGRAM_NAME=binaries/Linux/intel/musl/vlmcsd-x86-musl
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+
+
+
+# Linux x86 musl static threads
+export FEATURES=full
+export PROGRAM_NAME=binaries/Linux/intel/static/vlmcsd-x86-musl-static-threads
+export CC=/opt/toolchains/i386_i486_gcc-4.9-linaro_musl-1.1.6/bin/i486-openwrt-linux-musl-gcc-4.9.2
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m32 -march=i686 -mtune=generic"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -static"
+export THREADS=1
+export NOPROCFS=0
+export AUXV=1
+
+make $MAKEFLAGS $PROGRAM_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $PROGRAM_NAME
+ exit $?
+fi
+
+
+
+
+
+# Linux x32 glibc
+#export FEATURES=full
+#export MULTI_NAME=binaries/Linux/intel/glibc/vlmcsdmulti-x32-glibc
+#export CLIENT_NAME=binaries/Linux/intel/glibc/vlmcs-x32-glibc
+#export PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x32-glibc
+#export CC=gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mx32 -march=nocona -mtune=generic"
+#export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+#export THREADS=0
+#export NOPROCFS=0
+#export AUXV=1
+#
+#make DNS_PARSER=OS $MAKEFLAGS binaries/Linux/intel/glibc/vlmcsdmulti-x32-glibc
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make DNS_PARSER=OS $REUSEOBJFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#
+#
+#
+## Linux x32 glibc threads
+#export FEATURES=full
+#export PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x32-glibc-threads
+#export CC=gcc
+#export CFLAGS="$SMALLCC"
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mx32 -march=nocona -mtune=generic"
+#export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -lpthread"
+#export THREADS=1
+#export NOPROCFS=0
+#export AUXV=1
+#
+#make DNS_PARSER=OS $MAKEFLAGS $PROGRAM_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $PROGRAM_NAME
+# exit $?
+#fi
+
+
+
+
+# Linux armv4 little-endian glibc
+export FEATURES=full
+export MULTI_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsdmulti-armv4el-glibc
+export CLIENT_NAME=binaries/Linux/arm/little-endian/glibc/vlmcs-armv4el-glibc
+export PROGRAM_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsd-armv4el-glibc
+export CC=/opt/toolchains/armelv5t-glibc-2.20/bin/arm-linux-gcc
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv4 -marm"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+export NOPROCFS=0
+export AUXV=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux armv4 little-endian glibc thumb instruction set
+
+export MULTI_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsdmulti-armv4el-glibc-thumb
+export CLIENT_NAME=binaries/Linux/arm/little-endian/glibc/vlmcs-armv4el-glibc-thumb
+export PROGRAM_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsd-armv4el-glibc-thumb
+export CC=/opt/toolchains/armelv5t-glibc-2.20/bin/arm-linux-gcc
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv4t -mthumb"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux armv5 little-endian glibc thumb instruction set
+export PROGRAM_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsd-armv5el-glibc-thumb
+export CLIENT_NAME=binaries/Linux/arm/little-endian/glibc/vlmcs-armv5el-glibc-thumb
+export MULTI_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsdmulti-armv5el-glibc-thumb
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv5t -mthumb"
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+# Linux armv5 little-endian glibc
+export PROGRAM_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsd-armv5el-glibc
+export CLIENT_NAME=binaries/Linux/arm/little-endian/glibc/vlmcs-armv5el-glibc
+export MULTI_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsdmulti-armv5el-glibc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv5 -marm"
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux armv7 little-endian glibc thumb2 instruction set
+export PROGRAM_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsd-armv7el-glibc
+export CLIENT_NAME=binaries/Linux/arm/little-endian/glibc/vlmcs-armv7el-glibc
+export MULTI_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsdmulti-armv7el-glibc
+export CC=/opt/toolchains/armelv7-cortex-a8-glibc-2.18/usr/bin/arm-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv7 -mthumb"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux armv4 little-endian openwrt toolchain
+export PROGRAM_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsd-armv4el-openwrt-glibc
+export CLIENT_NAME=binaries/Linux/arm/little-endian/glibc/vlmcs-armv4el-openwrt-glibc
+export MULTI_NAME=binaries/Linux/arm/little-endian/glibc/vlmcsdmulti-armv4el-openwrt-glibc
+export CC=~/openwrt/staging_dir/toolchain-arm_mpcore+vfp_gcc-4.8-linaro_eglibc-2.19_eabi/bin/arm-openwrt-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv4"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+
+# Linux armv7 little-endian openwrt toolchain thumb 2 instruction set
+INSTALLDIR=binaries/Linux/arm/little-endian/glibc/
+SUFFIX=-armv7el-openwrt-glibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=~/openwrt/staging_dir/toolchain-arm_mpcore+vfp_gcc-4.8-linaro_eglibc-2.19_eabi/bin/arm-openwrt-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv7 -mthumb"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+# Linux armv5 little endian thumb instruction set
+INSTALLDIR=binaries/Linux/arm/little-endian/static/
+SUFFIX=-armv5el-musl-thumb
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}-static
+export CC=/opt/toolchains/armelv5t-musl/usr/bin/arm-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -static"
+export THREADS=0
+export NOPROCFS=0
+export AUXV=1
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+INSTALLDIR=binaries/Linux/arm/little-endian/musl/
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+INSTALLDIR=binaries/Linux/arm/little-endian/static/
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -static"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux armv5 little-endian uclibc thumb instruction set
+INSTALLDIR=binaries/Linux/arm/little-endian/uclibc/
+SUFFIX=-armv5el-uclibc-thumb
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/armelv5t-uclibc-0.9.33/usr/bin/arm-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv5t -mthumb"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+export NOPROCFS=0
+export AUXV=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux armv7 little-endian uclibc thumb 2 instruction set
+INSTALLDIR=binaries/Linux/arm/little-endian/
+SUFFIX=-armv7el-uclibc
+export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/armelv7-cortex-a8-uclibc-0.9.33/usr/bin/arm-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv7 -mthumb"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux armv4 little-endian uclibc openwrt toolchain
+INSTALLDIR=binaries/Linux/arm/little-endian/uclibc/
+SUFFIX=-armv4el-openwrt-uclibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=~/openwrt/staging_dir/toolchain-arm_mpcore+vfp_gcc-4.8-linaro_uClibc-0.9.33.2_eabi/bin/arm-openwrt-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv4 -marm"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+## Linux armv4 little-endian uclibc openwrt toolchain thumb instruction set
+#INSTALLDIR=binaries/Linux/arm/little-endian/uclibc/
+#SUFFIX=-armv4el-openwrt-uclibc-thumb
+#export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+#export CC=~/openwrt/staging_dir/toolchain-arm_mpcore+vfp_gcc-4.8-linaro_uClibc-0.9.33.2_eabi/bin/arm-openwrt-linux-gcc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv4t -mthumb"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+#export THREADS=0
+#
+#make $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+
+
+
+# Linux armv7 little-endian uclibc openwrt toolchain thumb 2 instruction set
+INSTALLDIR=binaries/Linux/arm/little-endian/uclibc/
+SUFFIX=-armv7el-openwrt-uclibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=~/openwrt/staging_dir/toolchain-arm_mpcore+vfp_gcc-4.8-linaro_uClibc-0.9.33.2_eabi/bin/arm-openwrt-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv7 -mthumb"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+##Linux armv4 little-endian uclibc
+#INSTALLDIR=binaries/Linux/arm/little-endian/
+#SUFFIX=-armv4el-uclibc
+#export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+#export CC=/root/cross-compiler-armv4l/bin/armv4l-gcc
+#export PLATFORMFLAGS="-pipe"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="-Wl,-z,norelro -fwhole-program"
+#export THREADS=0
+#export NOPROCFS=1
+#
+#make $MAKEFLAGS $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME CAT=2
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+#export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+#export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+#export LDFLAGS="-Wl,-z,norelro -fwhole-program -static"
+#
+#make $REUSEOBJFLAGS $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME CAT=2
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+
+
+
+
+
+## mips1 little-endian with openssl 0.9.8 support dreambox toolchain
+#INSTALLDIR=binaries/Linux/mips/little-endian/glibc/
+#SUFFIX=-mips1el-glibc-openssl0.9.8-soft-EXPERIMENTAL
+#export CRYPTO=openssl_with_aes_soft
+#export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/mipsoe20/bin/mipsel-unknown-linux-gnu-gcc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="$SMALLLD"
+#export THREADS=0
+#export NOPROCFS=0
+#
+#make $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#
+#
+#
+## mips1 little-endian dreambox toolchain
+#INSTALLDIR=binaries/Linux/mips/little-endian/glibc/
+#SUFFIX=-mips1el-glibc
+#export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/mipsoe20/bin/mipsel-unknown-linux-gnu-gcc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="$SMALLLD"
+#export THREADS=0
+#export CRYPTO=internal
+#
+#make $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#
+
+
+# Linux mips1 little-endian uclibc
+#INSTALLDIR=binaries/Linux/mips/little-endian/
+#SUFFIX=-mips1el-uclibc
+#export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+#export CC=/root/cross-compiler-mipsel/bin/mipsel-gcc
+#export PLATFORMFLAGS="-pipe"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="-Wl,-z,norelro -fwhole-program"
+#export THREADS=0
+#export CRYPTO=internal
+#export NOPROCFS=1
+#
+#make $MAKEFLAGS CAT=2 $CLIENT_NAME $MULTI_NAME $PROGRAM_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+#export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+#export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+#export LDFLAGS="-Wl,-z,norelro -fwhole-program -static"
+#
+#make $REUSEOBJFLAGS CAT=2 $CLIENT_NAME $MULTI_NAME $PROGRAM_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+
+
+
+
+# Linux mips16 little endian glibc
+INSTALLDIR=binaries/Linux/mips/little-endian/glibc/
+SUFFIX=-mips16el-glibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32el-mips16-glibc-2.18/usr/bin/mipsel-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips32 -mips16"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+export NOPROCFS=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux mips16 little-endian uclibc
+INSTALLDIR=binaries/Linux/mips/little-endian/uclibc/
+SUFFIX=-mips16el-uclibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32el-mips16-uclibc-0.9.33/bin/mipsel-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips32 -mips16"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+## Linux PowerPC glibc with SSL support and Dreambox 500 toolchain
+#INSTALLDIR=binaries/Linux/ppc/big-endian/glibc/
+#SUFFIX=-ppc-glibc-openssl0.9.8-soft-EXPERIMENTAL
+#export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/powerpc/bin/powerpc-linux-gcc
+#export PLATFORMFLAGS="-pipe"
+#export FEATURES=full
+#export CFLAGS="-fno-common -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
+#export LDFLAGS="-Wl,--no-gc-sections -Wl,-z,norelro"
+#export THREADS=0
+#export CRYPTO=internal
+#
+#make NO_DNS=1 $MAKEFLAGS CAT=2 $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+
+
+
+
+
+
+#Linux PowerPC uclibc OpenWRT toolchain
+INSTALLDIR=binaries/Linux/ppc/big-endian/
+SUFFIX=-ppc-uclibc
+export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+#export CC=~/openwrt/staging_dir/toolchain-powerpc_405_gcc-4.8-linaro_uClibc-0.9.33.2/bin/powerpc-openwrt-linux-gcc
+export CC=/opt/toolchains/ppc-uclibc0.9.33.2-gcc-4.9.1-binutils2.24/bin/powerpc-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -L/root/cross-compiler-powerpc/lib -L/root/cross-compiler-powerpc/usr/lib"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="$SMALLLD -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+export LDFLAGS="$SMALLLD"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+##Fritzbox 7170 (mips32r2 little-endian) device specific, May or may not run on other devices
+#INSTALLDIR=binaries/Linux/mips/little-endian/
+#SUFFIX=-mips32r2el-Fritzbox-71xx-72xx-uclibc
+#export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/fritz71xx/bin/mipsel-linux-uclibc-gcc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=4kec -mtune=4kec"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="$SMALLLD"
+#export THREADS=0
+#export CRYPTO=internal
+#
+#make NOLRESOLV=1 $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+
+#export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+#export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+#export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+#export LDFLAGS="$SMALLLD -static"
+#
+#make NOLRESOLV=1 $REUSEOBJFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLRESOLV=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+#export LDFLAGS="$SMALLLD"
+#
+#make NOLRESOLV=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+
+
+
+##Fritzbox 7370 (mips32r2 big-endian) device specific, May or may not run on other devices
+#INSTALLDIR=binaries/Linux/mips/big-endian/
+#SUFFIX=-mips16-Fritzbox-33xx-73xx-74xx-63xx-64xx-uclibc
+#export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/fritz73xxOS62/bin/mips-linux-cc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=24kc -mtune=24kc -mips16 -mdsp"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="$SMALLLD"
+#export THREADS=0
+#export CRYPTO=internal
+#
+#make NOLRESOLV=1 $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+#export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+#export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+#export LDFLAGS="$SMALLLD -static"
+#
+#make NOLRESOLV=1 $REUSEOBJFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLRESOLV=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+#export LDFLAGS="$SMALLLD"
+#
+#make NOLRESOLV=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+
+
+
+##Fritzbox 7370 (mips32r2 big-endian) device specific with _PEDANTIC, May or may not run on other devices
+#INSTALLDIR=binaries/Linux/mips/big-endian/uclibc/
+#SUFFIX=-mips16-Fritzbox-33xx-73xx-74xx-63xx-64xx-uclibc-pedantic
+#export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/fritz73xxOS62/bin/mips-linux-cc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=24kc -mtune=24kc -mips16 -mdsp"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC -D_PEDANTIC"
+#export LDFLAGS="$SMALLLD"
+#export THREADS=0
+#export CRYPTO=internal
+#
+#make NOLRESOLV=1 $MAKEFLAGS $PROGRAM_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $PROGRAM_NAME
+# exit $?
+#fi
+#
+
+
+
+##Fritzbox 7370 (mips32r2 big-endian) device specific inetd start only, May or may not run on other devices
+#INSTALLDIR=binaries/Linux/mips/big-endian/uclibc/
+#SUFFIX=-mips16-Fritzbox-33xx-73xx-74xx-63xx-64xx-uclibc-inetd
+#export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/fritz73xxOS62/bin/mips-linux-cc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=24kc -mtune=24kc -mips16 -mdsp"
+#export FEATURES=inetd
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="$SMALLLD"
+#export THREADS=0
+#export CRYPTO=internal
+#
+#make NOLRESOLV=1 $MAKEFLAGS $PROGRAM_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $PROGRAM_NAME
+# exit $?
+#fi
+#
+#
+#
+#
+##Fritzbox 7370 (mips32r2 big-endian) device specific with pthreads, May or may not run on other devices
+#INSTALLDIR=binaries/Linux/mips/big-endian/uclibc/
+#SUFFIX=-mips16-Fritzbox-33xx-73xx-74xx-63xx-64xx-uclibc-threads
+#export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/fritz73xxOS62/bin/mips-linux-cc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=24kc -mtune=24kc -mips16 -mdsp"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="$SMALLLD -lpthread"
+#export THREADS=1
+#
+#make NOLRESOLV=1 $MAKEFLAGS $PROGRAM_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $PROGRAM_NAME
+# exit $?
+#fi
+#
+#
+#
+#
+##Fritzbox 7370 (mips32r2 big-endian) device specific with OpenSSL support, May or may not run on other devices
+#INSTALLDIR=binaries/Linux/mips/big-endian/uclibc/
+#SUFFIX=-mips16-Fritzbox-33xx-73xx-74xx-63xx-64xx-uclibc-openssl0.9.8-soft-EXPERIMENTAL
+#export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/fritz73xxOS62/bin/mips-linux-cc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=24kc -mtune=24kc -mips16 -mdsp"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="$SMALLLD"
+#export THREADS=0
+#export CRYPTO=openssl_with_aes_soft
+#export OPENSSL_HMAC=0
+#
+#make NOLRESOLV=1 $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make NOLRESOLV=1 $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+#
+#unset OPENSSL_HMAC
+#
+#
+#
+#make $MAKEFLAGS CLIENT_NAME=binaries/Linux/mips/big-endian/uclibc/vlmcs-mips32-uclibc CFLAGS="$SMALL -pipe -flto=jobserver -fwhole-program" PROGRAM_NAME=binaries/Linux/mips/big-endian/uclibc/vlmcsd-mips32-uclibc CC=/opt/toolchains/mips32eb-uclibc-0.9.33/usr/bin/mips-linux-cc && \
+#Linux mips32 big-endian uclibc
+INSTALLDIR=binaries/Linux/mips/big-endian/uclibc/
+SUFFIX=-mips32-uclibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32eb-uclibc-0.9.33/usr/bin/mips-linux-cc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips32"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux mips16 big-endian uclibc
+INSTALLDIR=binaries/Linux/mips/big-endian/uclibc/
+SUFFIX=-mips16-uclibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32eb-uclibc-0.9.33/usr/bin/mips-linux-cc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips16"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Atheros ar7xxx/ar9xxx chips with OpenWRT toolchain (mips16 big-endian) device specific, May or may not run on other devices
+INSTALLDIR=binaries/Linux/mips/big-endian/
+SUFFIX=-mips16-openwrt-atheros-ar7xxx-ar9xxx-uclibc
+export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips-openwrt-linux-uclibc/bin/mips-openwrt-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=24kc -mips16"
+export FEATURES=full
+export CFLAGS="$SMALLCC -DNO_LIMIT"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+
+#Atheros ar7xxx/ar9xxx chips with OpenWRT toolchain (mips16 big-endian) device specific, May or may not run on other devices
+INSTALLDIR=binaries/Linux/mips/big-endian/
+SUFFIX=-mips16-openwrt-atheros-ar7xxx-ar9xxx-musl
+export PROGRAM_NAME=${INSTALLDIR}musl/vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}musl/vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}musl/vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips_34kc_gcc-4.9-linaro_musl-1.1.6-mips16/bin/mips-openwrt-linux-musl-gcc-4.9.2
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=24kc -mips16"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="$LDFLAGS -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=${INSTALLDIR}musl/vlmcsdmulti${SUFFIX}
+export LDFLAGS="$SMALLLD"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Atheros ar7xxx/ar9xxx chips with OpenWRT toolchain (mips32r2 big-endian) device specific, May or may not run on other devices
+INSTALLDIR=binaries/Linux/mips/big-endian/
+SUFFIX=-mips32r2-openwrt-atheros-ar7xxx-ar9xxx-uclibc
+export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips-openwrt-linux-uclibc/bin/mips-openwrt-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=24kc"
+export FEATURES=full
+export CFLAGS="$SMALLCC -DNO_LIMIT"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="$SMALLLD -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+export LDFLAGS="$SMALLLD"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux mips16 big-endian uclibc threads
+INSTALLDIR=binaries/Linux/mips/big-endian/uclibc/
+SUFFIX=-mips16-uclibc-threads
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32eb-uclibc-0.9.33/usr/bin/mips-linux-cc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips16"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -lpthread"
+export THREADS=1
+export CRYPTO=internal
+
+make $MAKEFLAGS $PROGRAM_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+
+
+
+# Linux mips32 big-endian glibc
+INSTALLDIR=binaries/Linux/mips/big-endian/glibc/
+SUFFIX=-mips32-glibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32eb-glibc-2.19/usr/bin/mips-linux-cc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux mips16 big-endian glibc
+INSTALLDIR=binaries/Linux/mips/big-endian/glibc/
+SUFFIX=-mips16-glibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32eb-glibc-2.19/usr/bin/mips-linux-cc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips16"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Linux mips32 big-endian musl
+INSTALLDIR=binaries/Linux/mips/big-endian/
+SUFFIX=-mips32-musl
+export PROGRAM_NAME=${INSTALLDIR}musl/vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}musl/vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}musl/vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32eb-musl/usr/bin/mips-linux-cc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips32"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+export NOPROCFS=0
+export AUXV=1
+
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="$SMALLLD -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=${INSTALLDIR}musl/vlmcsdmulti${SUFFIX}
+export LDFLAGS="$SMALLLD"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Linux mips16 little-endian musl soft-float
+INSTALLDIR=binaries/Linux/mips/little-endian/
+SUFFIX=-mips16el-musl
+export PROGRAM_NAME=${INSTALLDIR}musl/vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}musl/vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}musl/vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32el-mips16-musl/usr/bin/mipsel-linux-cc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips16"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+export NOPROCFS=0
+export AUXV=1
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="$SMALLLD -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=${INSTALLDIR}musl/vlmcsdmulti${SUFFIX}
+export LDFLAGS="$SMALLLD"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Linux mips16 little-endian musl fpu
+INSTALLDIR=binaries/Linux/mips/little-endian/
+SUFFIX=-mips16el-musl-fpu
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export CC=/opt/toolchains/mips32el-mips16-musl-fpu/usr/bin/mipsel-linux-cc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips16"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -static"
+export THREADS=0
+export CRYPTO=internal
+export NOPROCFS=0
+export AUXV=1
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+# Linux x86 uclibc
+INSTALLDIR=binaries/Linux/intel/uclibc/
+SUFFIX=-x86-uclibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/i486-uclibc-0.9.33/bin/i486-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m32 -march=i486 -mtune=generic"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+export CRYPTO=internal
+export NOPROCFS=0
+export AUXV=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+#make $MAKEFLAGS CLIENT_NAME=binaries/Linux/intel/glibc/vlmcs-x64-glibc LDFLAGS="-Wl,--hash-style=gnu" CFLAGS="$SMALL -pipe -flto=jobserver -fwhole-program" PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x64-glibc CC=/opt/toolchains/x86_64-glibc-2.19/usr/bin/x86_64-linux-gcc PLATFORMFLAGS="-m64 -mtune=generic"&& \
+# Linux x64 glibc
+INSTALLDIR=binaries/Linux/intel/glibc/
+SUFFIX=-x64-glibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/x86_64-glibc-2.19/usr/bin/x86_64-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m64 -mtune=generic"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#Linux Sparc32v7 glibc
+INSTALLDIR=binaries/Linux/sparc32/glibc/
+SUFFIX=-sparc32v7-glibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/sparc32-glibc-gcc-4.7.4/bin/sparc-buildroot-linux-gnu-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mcpu=v7"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -lpthread"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#make $MAKEFLAGS binaries/Linux/intel/glibc/vlmcsd-x64-glibc-threads CLIENT_NAME=binaries/Linux/intel/glibc/vlmcs-x64-glibc-threads THREADS=1 LDFLAGS="-Wl,--hash-style=gnu -lpthread" CFLAGS="-pipe -flto=jobserver -fwhole-program" PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x64-glibc-threads CC=/opt/toolchains/x86_64-glibc-2.19/usr/bin/x86_64-linux-gcc PLATFORMFLAGS="-m64 -mtune=generic"&& \
+# Linux x64 glibc with threads
+INSTALLDIR=binaries/Linux/intel/glibc/
+SUFFIX=-x64-glibc-threads
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/x86_64-glibc-2.19/usr/bin/x86_64-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m64 -mtune=generic"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -lpthread"
+export THREADS=1
+export CRYPTO=internal
+
+make $MAKEFLAGS $PROGRAM_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+
+
+
+#make $MAKEFLAGS LDFLAGS="-Wl,--hash-style=gnu" CLIENT_NAME=binaries/Linux/intel/glibc/vlmcs-x64-glibc-openssl1.0.0-hard-EXPERIMENTAL CRYPTO=openssl_with_aes CFLAGS="$SMALL -pipe -flto=jobserver -fwhole-program" PROGRAM_NAME=binaries/Linux/intel/glibc/vlmcsd-x64-glibc-openssl1.0.0-hard-EXPERIMENTAL CC=/opt/toolchains/x86_64-glibc-2.19/usr/bin/x86_64-linux-gcc PLATFORMFLAGS="-m64 -mtune=generic" && \
+# Linux x64 glibc with OpenSSL 1.0.x support
+INSTALLDIR=binaries/Linux/intel/glibc/
+SUFFIX=-x64-glibc-openssl1.0.0-hard-EXPERIMENTAL
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/x86_64-glibc-2.19/usr/bin/x86_64-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m64 -mtune=generic"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+export CRYPTO=openssl_with_aes
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+# Linux x64 musl
+INSTALLDIR=binaries/Linux/intel/
+SUFFIX=-x64-musl
+export PROGRAM_NAME=${INSTALLDIR}musl/vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}musl/vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}musl/vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/x86_64_gcc-4.9-linaro_musl-1.1.6/bin/x86_64-openwrt-linux-musl-gcc-4.9.2
+#export CC=/opt/toolchains/x86_64-musl/usr/bin/x86_64-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m64 -mtune=generic"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+export CRYPTO=internal
+export NOPROCFS=0
+export AUXV=1
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=${INSTALLDIR}musl/vlmcsdmulti${SUFFIX}
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+#make $MAKEFLAGS CC=/opt/toolchains/x86_64-uclibc-0.9.33/bin/x86_64-linux-gcc LDFLAGS="-Wl,--hash-style=gnu" CLIENT_NAME=binaries/Linux/intel/uclibc/vlmcs-x64-uclibc PROGRAM_NAME=binaries/Linux/intel/uclibc/vlmcsd-x64-uclibc CFLAGS="$SMALL -flto=jobserver -fwhole-program -pipe -fno-stack-protector" && \
+# Linux x64 uclibc
+INSTALLDIR=binaries/Linux/intel/uclibc/
+SUFFIX=-x64-uclibc
+export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/x86_64-uclibc-0.9.33/bin/x86_64-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m64 -mtune=generic"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+export CRYPTO=internal
+export NOPROCFS=0
+export AUXV=0
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+## mips32 little-endian DD-WRT toolchain with gcc 4.1.0
+#export CC=/opt/simplebuild/toolchains/ddwrt410/bin/mipsel-linux-gcc
+#INSTALLDIR=binaries/Linux/mips/little-endian/
+#SUFFIX=-mips32el-ddwrt-gcc$($CC -dumpversion)-uclibc
+#export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+#export PLATFORMFLAGS="-pipe -mips32"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="-fwhole-program"
+#export THREADS=0
+#export CRYPTO=internal
+#
+#make $MAKEFLAGS CAT=2 $PROGRAM_NAME $MULTI_NAME $CLIENT_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $PROGRAM_NAME, $MULTI_NAME and/or $CLIENT_NAME
+# exit $?
+#fi
+#
+#export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+#export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+#export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+#export LDFLAGS="-fwhole-program -static"
+#
+#make $REUSEOBJFLAGS CAT=2 $PROGRAM_NAME $MULTI_NAME $CLIENT_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $PROGRAM_NAME, $MULTI_NAME and/or $CLIENT_NAME
+# exit $?
+#fi
+
+
+
+
+
+#Linux mips32 little-endian uclibc
+INSTALLDIR=binaries/Linux/mips/little-endian/
+SUFFIX=-mips32el-uclibc
+export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+export CC=/opt/toolchains/mips32el-uclibc-0.9.33/bin/mipsel-linux-gcc
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips32"
+export FEATURES=full
+export CFLAGS="$SMALLCC"
+export LDFLAGS="$SMALLLD"
+export THREADS=0
+export CRYPTO=internal
+
+make $MAKEFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="$SMALLLD -static"
+
+make $REUSEOBJFLAGS
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+export LDFLAGS="$SMALLLD"
+
+make $REUSEOBJFLAGS $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $MULTI_NAME
+ exit $?
+fi
+
+
+
+
+##Linux armv6 hard-float little-endian. Used on Raspberry Pi with Raspbian.
+##The hard-float ABI cannot be combined with thumb.
+##You may wish to use armv5el-thumb instead because the binary is smaller
+#INSTALLDIR=binaries/Linux/arm/little-endian/glibc/
+#SUFFIX=-armv6hf-Raspberry-glibc
+#export PROGRAM_NAME=${INSTALLDIR}vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}vlmcsdmulti${SUFFIX}
+#export CC=/opt/toolchains/armhfv6-glibc-2.19/bin/arm-linux-gcc
+#export PLATFORMFLAGS="-flto=jobserver -fwhole-program -march=armv6zk -mfpu=vfp -mfloat-abi=hard -mtune=arm1176jzf-s"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+#export THREADS=0
+#export CRYPTO=internal
+#
+#make $MAKEFLAGS
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+#
+#rm -f *_all.c vlmcsd.o vlmcs.o vlmcsdmulti.o 2> /dev/null
+#
+#make $REUSEOBJFLAGS $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $MULTI_NAME
+# exit $?
+#fi
+
+
+
+
+## Linux arm big-endian uclibc
+#INSTALLDIR=binaries/Linux/arm/big-endian/
+#SUFFIX=-armeb-nslu2-uclibc
+#export PROGRAM_NAME=${INSTALLDIR}uclibc/vlmcsd${SUFFIX}
+#export CLIENT_NAME=${INSTALLDIR}uclibc/vlmcs${SUFFIX}
+#export MULTI_NAME=${INSTALLDIR}uclibc/vlmcsdmulti${SUFFIX}
+#export CC=/opt/simplebuild/toolchains/nslu2open/bin/armeb-linux-uclibc-gcc
+#export PLATFORMFLAGS="-pipe"
+#export FEATURES=full
+#export CFLAGS="$SMALLCC"
+#export LDFLAGS="-Wl,-z,norelo"
+#export THREADS=0
+#
+#make $MAKEFLAGS CAT=2 $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+#
+#if [ $? != 0 ]; then
+# echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+# exit $?
+#fi
+
+export PROGRAM_NAME=${INSTALLDIR}static/vlmcsd${SUFFIX}-static
+export CLIENT_NAME=${INSTALLDIR}static/vlmcs${SUFFIX}-static
+export MULTI_NAME=${INSTALLDIR}static/vlmcsdmulti${SUFFIX}-static
+export LDFLAGS="-Wl,-z,norelo -static"
+
+make $REUSEOBJFLAGS CAT=2 $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+
+if [ $? != 0 ]; then
+ echo Error creating $CLIENT_NAME, $MULTI_NAME and/or $PROGRAM_NAME
+ exit $?
+fi
+
+
+# Strip off unnecessary stuff from binaries
+
+find binaries -xdev -name 'vlmcs*' -exec /opt/toolchains/mips32el-mips16-glibc-2.18/usr/bin/mipsel-linux-strip -s --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag {} \; 2>/dev/null
+find binaries -xdev -name 'vlmcs*' -exec strip -s --strip-unneeded --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag {} \; 2>/dev/null
+find binaries -xdev -name 'vlmcs*' -exec sstrip -z {} \; 2>/dev/null
+
+make alldocs
+
+rm *.o
+
+#cp -p binaries/Linux/intel/glibc/vlmcs-x32-glibc /usr/local/bin/vlmcs
+
+cp -pf binaries/Linux/intel/glibc/vlmcsdmulti-x64-glibc /usr/local/sbin/vlmcsdmulti
+
+ln -s vlmcsdmulti /usr/local/sbin/vlmcsd 2>/dev/null
+ln -s ../sbin/vlmcsdmulti /usr/local/bin/vlmcs 2>/dev/null
+mkdir -p /usr/local/man/man1 2>/dev/null
+mkdir -p /usr/local/man/man5 2>/dev/null
+mkdir -p /usr/local/man/man8 2>/dev/null
+mkdir -p /usr/local/man/man7 2>/dev/null
+cp -a vlmcs.1 vlmcsdmulti.1 /usr/local/man/man1/
+cp -a vlmcsd.7 /usr/local/man/man7/
+cp -a vlmcsd.8 /usr/local/man/man8/
+cp -a vlmcsd.ini.5 /usr/local/man/man5/
+pbzip2 -f -9 /usr/local/man/man5/vlmcsd.ini.5 /usr/local/man/man1/vlmcs.1 /usr/local/man/man1/vlmcsdmulti.1 /usr/local/man/man7/vlmcsd.7 /usr/local/man/man8/vlmcsd.8
+#pbzip2 -f /usr/local/man/man7/vlmcsd.7
+#pbzip2 -f /usr/local/man/man8/vlmcsd.8
+
+mandb >/dev/null 2>&1
+
diff --git a/make_mainframe_linux b/make_mainframe_linux
deleted file mode 100755
index 6185263..0000000
--- a/make_mainframe_linux
+++ /dev/null
@@ -1,50 +0,0 @@
-#!/bin/bash
-
-SMALLCC="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
-SMALLLD="-pipe -Wl,--hash-style=sysv -Wl,-z,norelro -Wl,--build-id=none"
-SMALL="$SMALLCC $SMALLLD"
-
-export CFLAGS="$SMALLCC"
-export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m31 -mesa -mpacked-stack -msmall-exec"
-export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
-export THREADS=0
-export FEATURES=full
-
-export MULTI_NAME=vlmcsdmulti-s390-glibc
-export CLIENT_NAME=vlmcs-s390-glibc
-export PROGRAM_NAME=vlmcsd-s390-glibc
-
-make -B -j`nproc` $CLIENT_NAME $PROGRAM_NAME
-
-rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
-make -j`nproc` $MULTI_NAME
-
-sstrip -z $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
-
-export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m64 -mzarch -mpacked-stack -msmall-exec"
-export MULTI_NAME=vlmcsdmulti-s390x-glibc
-export CLIENT_NAME=vlmcs-s390x-glibc
-export PROGRAM_NAME=vlmcsd-s390x-glibc
-
-make -B -j`nproc` $CLIENT_NAME $PROGRAM_NAME
-
-rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
-export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m64 -mzarch -mpacked-stack -msmall-exec"
-make -j`nproc` $MULTI_NAME
-
-sstrip -z $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
-
-cp -af vlmcsd-s390-glibc /usr/local/sbin/vlmcsd
-cp -af vlmcs-s390-glibc /usr/local/bin/vlmcs
-
-mkdir -p /usr/local/man/man1 2>/dev/null
-mkdir -p /usr/local/man/man5 2>/dev/null
-mkdir -p /usr/local/man/man8 2>/dev/null
-mkdir -p /usr/local/man/man7 2>/dev/null
-cp -a vlmcs.1 vlmcsdmulti.1 /usr/local/man/man1/
-cp -a vlmcsd.7 /usr/local/man/man7/
-cp -a vlmcsd.8 /usr/local/man/man8/
-cp -a vlmcsd.ini.5 /usr/local/man/man5/
-pbzip2 -f -9 /usr/local/man/man5/vlmcsd.ini.5 /usr/local/man/man1/vlmcs.1 /usr/local/man/man1/vlmcsdmulti.1 /usr/local/man/man7/vlmcsd.7 /usr/local/man/man8/vlmcsd.8
-
-scp -p vlmcsdmulti-s390-glibc vlmcs-s390-glibc vlmcsd-s390-glibc vlmcsdmulti-s390x-glibc vlmcs-s390x-glibc vlmcsd-s390x-glibc ubuntu64.internal:x/binaries/Linux/s390/glibc
diff --git a/make_multilib_linux b/make_multilib_linux
new file mode 100755
index 0000000..7b1050e
--- /dev/null
+++ b/make_multilib_linux
@@ -0,0 +1,137 @@
+#!/bin/bash
+
+SMALLCC="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
+SMALLLD="-pipe -Wl,--hash-style=sysv -Wl,-z,norelro -Wl,--build-id=none"
+SMALL="$SMALLCC $SMALLLD"
+
+rm -f vlmcsd vlmcs vlmcsdmulti vlmcsd-* vlmcs-* vlmcsdmulti-*
+
+## IBM S/390
+
+export CFLAGS="$SMALLCC"
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m31 -mesa -mpacked-stack -msmall-exec"
+export LDFLAGS="$SMALLLD -Wl,--hash-style=gnu"
+export THREADS=0
+export FEATURES=full
+export CC=s390x-linux-gnu-gcc
+export VERBOSE=3
+
+export MULTI_NAME=vlmcsdmulti-s390-glibc
+export CLIENT_NAME=vlmcs-s390-glibc
+export PROGRAM_NAME=vlmcsd-s390-glibc
+
+make -B -j`nproc` $CLIENT_NAME $PROGRAM_NAME
+
+rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
+make -j`nproc` $MULTI_NAME
+
+sstrip -z $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m64 -mzarch -mpacked-stack -msmall-exec"
+export MULTI_NAME=vlmcsdmulti-s390x-glibc
+export CLIENT_NAME=vlmcs-s390x-glibc
+export PROGRAM_NAME=vlmcsd-s390x-glibc
+
+make -B -j`nproc` $CLIENT_NAME $PROGRAM_NAME
+
+rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -m64 -mzarch -mpacked-stack -msmall-exec"
+make -j`nproc` $MULTI_NAME
+
+sstrip -z $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+
+
+## SPARC64
+
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mcpu=v7"
+export LDFLAGS="$SMALLLD"
+export CC=sparc64-linux-gnu-gcc
+
+export MULTI_NAME=vlmcsdmulti-sparc64v9-glibc
+export CLIENT_NAME=vlmcs-sparc64v9-glibc
+export PROGRAM_NAME=vlmcsd-sparc64v9-glibc
+
+make -B -j`nproc` $CLIENT_NAME $PROGRAM_NAME
+
+rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
+make -j`nproc` $MULTI_NAME
+sstrip -z $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+
+
+## MIPS64 BIG-ENDIAN
+
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips64 -mno-mips16"
+export LDFLAGS="$SMALLLD"
+export CC=mips64-linux-gnuabi64-gcc
+
+export MULTI_NAME=vlmcsdmulti-mips64-glibc
+export CLIENT_NAME=vlmcs-mips64-glibc
+export PROGRAM_NAME=vlmcsd-mips64-glibc
+
+make -B -j`nproc` $CLIENT_NAME $PROGRAM_NAME
+
+rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
+make -j`nproc` $MULTI_NAME
+sstrip -z $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips64 -mmicromips"
+export MULTI_NAME=vlmcsdmulti-mips64mm-glibc
+export CLIENT_NAME=vlmcs-mips64mm-glibc
+export PROGRAM_NAME=vlmcsd-mips64mm-glibc
+
+make -B -j`nproc` $CLIENT_NAME $PROGRAM_NAME
+
+rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
+make -j`nproc` $MULTI_NAME
+sstrip -z $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+
+
+## MIPS64 LITTLE-ENDIAN
+
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips64 -mno-mips16"
+export LDFLAGS="$SMALLLD"
+export CC=mips64el-linux-gnuabi64-gcc
+
+export MULTI_NAME=vlmcsdmulti-mips64el-glibc
+export CLIENT_NAME=vlmcs-mips64el-glibc
+export PROGRAM_NAME=vlmcsd-mips64el-glibc
+
+make -B -j`nproc` $CLIENT_NAME $PROGRAM_NAME
+
+rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
+make -j`nproc` $MULTI_NAME
+sstrip -z $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+
+export PLATFORMFLAGS="-flto=jobserver -fwhole-program -mips64 -mmicromips"
+export MULTI_NAME=vlmcsdmulti-mips64elmm-glibc
+export CLIENT_NAME=vlmcs-mips64elmm-glibc
+export PROGRAM_NAME=vlmcsd-mips64elmm-glibc
+
+make -B -j`nproc` $CLIENT_NAME $PROGRAM_NAME
+
+rm -f vlmcsd.o vlmcs.o vlmcsdmulti.o
+make -j`nproc` $MULTI_NAME
+sstrip -z $CLIENT_NAME $PROGRAM_NAME $MULTI_NAME
+
+
+
+if [ "$1" == "nocopy" ]; then
+ exit 0
+fi
+
+mkdir -p /usr/local/man/man1 2>/dev/null
+mkdir -p /usr/local/man/man5 2>/dev/null
+mkdir -p /usr/local/man/man8 2>/dev/null
+mkdir -p /usr/local/man/man7 2>/dev/null
+cp -a vlmcs.1 vlmcsdmulti.1 /usr/local/man/man1/
+cp -a vlmcsd.7 /usr/local/man/man7/
+cp -a vlmcsd.8 /usr/local/man/man8/
+cp -a vlmcsd.ini.5 /usr/local/man/man5/
+pbzip2 -f -9 /usr/local/man/man5/vlmcsd.ini.5 /usr/local/man/man1/vlmcs.1 /usr/local/man/man1/vlmcsdmulti.1 /usr/local/man/man7/vlmcsd.7 /usr/local/man/man8/vlmcsd.8
+
+scp -p vlmcsdmulti-s390-glibc vlmcs-s390-glibc vlmcsd-s390-glibc vlmcsdmulti-s390x-glibc vlmcs-s390x-glibc vlmcsd-s390x-glibc ubuntu64.internal:x/binaries/Linux/s390/glibc
+scp -p vlmcsdmulti-sparc64v9-glibc vlmcs-sparc64v9-glibc vlmcsd-sparc64v9-glibc ubuntu64.internal:x/binaries/Linux/sparc/glibc
+scp -p vlmcsdmulti-mips64-glibc vlmcs-mips64-glibc vlmcsd-mips64-glibc vlmcsdmulti-mips64mm-glibc vlmcs-mips64mm-glibc vlmcsd-mips64mm-glibc ubuntu64.internal:x/binaries/Linux/mips/big-endian/glibc
+scp -p vlmcsdmulti-mips64el-glibc vlmcs-mips64el-glibc vlmcsd-mips64el-glibc vlmcsdmulti-mips64elmm-glibc vlmcs-mips64elmm-glibc vlmcsd-mips64elmm-glibc ubuntu64.internal:x/binaries/Linux/mips/little-endian/glibc
+scp -p -P 2222 vlmcsdmulti-s390-glibc vlmcs-s390-glibc vlmcsd-s390-glibc vlmcsdmulti-s390x-glibc vlmcs-s390x-glibc vlmcsd-s390x-glibc s390:vlmcsd
+scp -p -P 2222 vlmcsdmulti-s390-glibc vlmcsdmulti-s390x-glibc s390:/usr/local/sbin
diff --git a/make_netbsd b/make_netbsd
index bae992e..1b57ebb 100755
--- a/make_netbsd
+++ b/make_netbsd
@@ -4,7 +4,7 @@ export VERBOSE=3
export DNS_PARSER=OS
rm -f vlmcsd-* vlmcs-* vlmcsdmulti-* *_all.* 2>/dev/null
-rm -f vlmcsdmulti vlmcsd vlmcs 2>/dev/null
+gmake clean
MAKEFLAGS="-B -j12"
REUSEOBJFLAGS="-j12"
@@ -15,17 +15,17 @@ CFCLANG="-pipe -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tabl
LF="-Wl,-z,norelro -Wl,--hash-style=sysv -Wl,--build-id=none"
LFCLANG="-Wl,-z,norelro -Wl,--hash-style=sysv"
-gmake $MAKEFLAGS CC=/usr/pkg/gcc49/bin/gcc PROGRAM_NAME=vlmcsd-NetBSD-x64 CLIENT_NAME=vlmcs-NetBSD-x64 CFLAGS="$CF" LDFLAGS="$LF"
+gmake $MAKEFLAGS CC=/usr/pkg/gcc5/bin/gcc PROGRAM_NAME=vlmcsd-NetBSD-x64 CLIENT_NAME=vlmcs-NetBSD-x64 CFLAGS="$CF" LDFLAGS="$LF"
rm vlmcsd.o vlmcs.o
-gmake vlmcsdmulti-NetBSD-x64 $REUSEOBJFLAGS CC=/usr/pkg/gcc49/bin/gcc CFLAGS="$CF" LDFLAGS="$LF" MULTI_NAME=vlmcsdmulti-NetBSD-x64
+gmake vlmcsdmulti-NetBSD-x64 $REUSEOBJFLAGS CC=/usr/pkg/gcc5/bin/gcc CFLAGS="$CF" LDFLAGS="$LF" MULTI_NAME=vlmcsdmulti-NetBSD-x64
-gmake allmulti $MAKEFLAGS CAT=2 MULTI_NAME=vlmcsdmulti-NetBSD-x86 PROGRAM_NAME=vlmcsd-NetBSD-x86 CLIENT_NAME=vlmcs-NetBSD-x86 CFLAGS="$CF45 -m32" LDFLAGS="$LF"
+gmake allmulti CC=gcc $MAKEFLAGS CAT=2 MULTI_NAME=vlmcsdmulti-NetBSD-x86 PROGRAM_NAME=vlmcsd-NetBSD-x86 CLIENT_NAME=vlmcs-NetBSD-x86 CFLAGS="$CF45 -m32" LDFLAGS="$LF"
#gmake $MAKEFLAGS CC=clang PROGRAM_NAME=vlmcsd-NetBSD-x64-clang CLIENT_NAME=vlmcs-NetBSD-x64-clang CFLAGS="$CFCLANG" LDFLAGS="$LFCLANG"
rm *.o
-strip -s --strip-unneeded --remove-section=.eh_frame_hdr --remove-section=.eh_frame --remove-section=.note.gnu.gold-version --remove-section=.comment --remove-section=.note --remove-section=.note.gnu.build-id --remove-section=.note.ABI-tag vlmcs-* vlmcsd-* vlmcsdmulti-*
+strip -s --strip-unneeded -R .ident -R .got -R .note.netbsd.pax -R .gnu.version -R .eh_frame -R .note.gnu.gold-version -R .comment -R .note -R .note.gnu.build-id -R .note.ABI-tag vlmcs-* vlmcsd-* vlmcsdmulti-*
#sstrip -z vlmcs-* vlmcsd-* vlmcsdmulti-*
cp -af vlmcsd-NetBSD-x86 /usr/local/sbin/vlmcsd
diff --git a/make_osx b/make_osx
index b42bc35..79852f7 100755
--- a/make_osx
+++ b/make_osx
@@ -6,7 +6,7 @@ export DNS_PARSER=OS
rm vlmcsd-* vlmcs-* vlmcsdmulti-* *_all.* 2>/dev/null
rm vlmcsd vlmcs vlmcsdmulti 2>/dev/null
-MAKEFLAGS="-j -B"
+MAKEFLAGS="-Bj"
REUSEOBJFLAGS="-j"
CFGCC="-static-libgcc -mdynamic-no-pic -Os -flto=jobserver -fwhole-program -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
CFCLANG="-mdynamic-no-pic -Os -flto -fno-common -fno-exceptions -fno-stack-protector -fno-unwind-tables -fno-asynchronous-unwind-tables -fmerge-all-constants"
@@ -27,12 +27,12 @@ make $MAKEFLAGS vlmcsd-MacOSX-x64-threads THREADS=1 PROGRAM_NAME=vlmcsd-MacOSX-x
rm -f vlmcs.o vlmcsd.o vlmcsdmulti.o *_all.* && \
#make $REUSEOBJFLAGS vlmcsdmulti-iOS-7.1-armv7 MULTI_NAME=vlmcsdmulti-iOS-7.1-armv7 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-mthumb -m32 -arch armv7 -miphoneos-version-min=1.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk" && \
-make $MAKEFLAGS CLIENT_NAME=vlmcs-iOS-9.1-armv7 PROGRAM_NAME=vlmcsd-iOS-9.1-armv7 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-mthumb -m32 -arch armv7 -miphoneos-version-min=1.0 -isysroot ~/toolchains/iPhoneOS9.1.sdk" && \
+make $MAKEFLAGS CLIENT_NAME=vlmcs-iOS-armv7 PROGRAM_NAME=vlmcsd-iOS-armv7 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-mthumb -m32 -arch armv7 -miphoneos-version-min=1.0 -isysroot ~/toolchains/iPhoneOS.sdk" && \
rm -f vlmcs.o vlmcsd.o vlmcsdmulti.o *_all.* && \
-make $REUSEOBJFLAGS vlmcsdmulti-iOS-9.1-armv7 MULTI_NAME=vlmcsdmulti-iOS-9.1-armv7 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-mthumb -m32 -arch armv7 -miphoneos-version-min=1.0 -isysroot ~/toolchains/iPhoneOS9.1.sdk" && \
-make $MAKEFLAGS CLIENT_NAME=vlmcs-iOS-9.1-armv8-aarch64 PROGRAM_NAME=vlmcsd-iOS-9.1-armv8-aarch64 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-m64 -arch arm64 -miphoneos-version-min=7.0 -isysroot ~/toolchains/iPhoneOS9.1.sdk" && \
+make $REUSEOBJFLAGS vlmcsdmulti-iOS-armv7 MULTI_NAME=vlmcsdmulti-iOS-armv7 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-mthumb -m32 -arch armv7 -miphoneos-version-min=1.0 -isysroot ~/toolchains/iPhoneOS.sdk" && \
+make $MAKEFLAGS CLIENT_NAME=vlmcs-iOS-armv8-aarch64 PROGRAM_NAME=vlmcsd-iOS-armv8-aarch64 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-m64 -arch arm64 -miphoneos-version-min=7.0 -isysroot ~/toolchains/iPhoneOS.sdk" && \
rm -f vlmcs.o vlmcsd.o vlmcsdmulti.o *_all.* && \
-make $REUSEOBJFLAGS vlmcsdmulti-iOS-9.1-armv8-aarch64 MULTI_NAME=vlmcsdmulti-iOS-9.1-armv8-aarch64 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-m64 -arch arm64 -miphoneos-version-min=7.0 -isysroot ~/toolchains/iPhoneOS9.1.sdk" && \
+make $REUSEOBJFLAGS vlmcsdmulti-iOS-armv8-aarch64 MULTI_NAME=vlmcsdmulti-iOS-armv8-aarch64 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-m64 -arch arm64 -miphoneos-version-min=7.0 -isysroot ~/toolchains/iPhoneOS.sdk" && \
make $MAKEFLAGS CLIENT_NAME=vlmcs-iOS-6.1-armv7 PROGRAM_NAME=vlmcsd-iOS-6.1-armv7 CC=clang CFLAGS="$CFCLANG" PLATFORMFLAGS="-mthumb -m32 -arch armv7 -miphoneos-version-min=1.0 --sysroot ~/toolchains/iPhoneOS6.1.sdk -isysroot ~/toolchains/iPhoneOS6.1.sdk" && \
rm -f vlmcs.o vlmcsd.o vlmcsdmulti.o *_all.* && \
@@ -56,9 +56,9 @@ PATH=~/toolchains/iOS5.1-MacOS-Lion/usr/bin:$PATH make $REUSEOBJFLAGS vlmcsdmult
#PATH=~/toolchains/gcc4.2/usr/bin:$PATH make $REUSEOBJFLAGS vlmcsdmulti-iOS-4.1-armv7-llvm-clang MULTI_NAME=vlmcsdmulti-iOS-4.1-armv7-llvm-clang CC=~/toolchains/gcc4.2/usr/bin/bin/clang CFLAGS="$CFGCC42" PLATFORMFLAGS="-mthumb -arch armv7 -miphoneos-version-min=4.1 --sysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.1.sdk -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.1.sdk" && \
-PATH=~/toolchains/gcc4.2/usr/bin:$PATH make -Bj PROGRAM_NAME=vlmcsd-MacOSX-ppc CLIENT_NAME=vlmcs-MacOSX-ppc CC=gcc CFLAGS="$CFGCC42 -isysroot ~/toolchains/MacOSX10.5.sdk -arch ppc -mmacosx-version-min=10.0" && \
+PATH=~/toolchains/gcc4.2/usr/bin:$PATH make -Bj SAFE_MODE=1 PROGRAM_NAME=vlmcsd-MacOSX-ppc CLIENT_NAME=vlmcs-MacOSX-ppc CC=gcc CFLAGS="$CFGCC42 -isysroot ~/toolchains/MacOSX10.5.sdk -arch ppc -mmacosx-version-min=10.0" && \
rm -f vlmcs.o vlmcsd.o vlmcsdmulti.o *_all.* && \
-PATH=~/toolchains/gcc4.2/usr/bin:$PATH make -j vlmcsdmulti-MacOSX-ppc MULTI_NAME=vlmcsdmulti-MacOSX-ppc CC=gcc CFLAGS="$CFGCC42 -isysroot ~/toolchains/MacOSX10.5.sdk -arch ppc -mmacosx-version-min=10.0"
+PATH=~/toolchains/gcc4.2/usr/bin:$PATH make -j SAFE_MODE=1 vlmcsdmulti-MacOSX-ppc MULTI_NAME=vlmcsdmulti-MacOSX-ppc CC=gcc CFLAGS="$CFGCC42 -isysroot ~/toolchains/MacOSX10.5.sdk -arch ppc -mmacosx-version-min=10.0"
make $MAKEFLAGS CLIENT_NAME=vlmcs-MacOSX-x86-gcc PROGRAM_NAME=vlmcsd-MacOSX-x86-gcc CC=gcc-5 CFLAGS="$CFGCC" PLATFORMFLAGS="-m32 -march=core2 -mmacosx-version-min=10.11" && \
diff --git a/make_windows b/make_windows
index 8666a20..c077cfe 100755
--- a/make_windows
+++ b/make_windows
@@ -10,18 +10,18 @@ CF="-Wno-missing-braces -fno-common -fno-exceptions -fno-non-call-exceptions -fn
CFMSRPC="-Wno-missing-braces -Wno-unused-variable $CF" # -fno-common -fno-stack-protector -fmerge-all-constants -pipe"
PF32=""
PF64="-mpreferred-stack-boundary=4 -march=nocona -mtune=generic"
-LFCYG32="-fwhole-program -Wl,--nxcompat,--dynamicbase,--tsaware,--large-address-aware"
-LFWIN32="-fwhole-program -lws2_32 -Wl,--nxcompat,--dynamicbase,--tsaware,--large-address-aware"
-LFCYG64="-fwhole-program -Wl,--nxcompat,--dynamicbase,--tsaware"
-LFWIN64="-fwhole-program -lws2_32 -Wl,--nxcompat,--dynamicbase,--tsaware"
+LFCYG32="-fwhole-program -Wl,--nxcompat,--dynamicbase,--tsaware,--large-address-aware,--disable-long-section-names"
+LFWIN32="-fwhole-program -lws2_32 -Wl,--nxcompat,--dynamicbase,--tsaware,--large-address-aware,--disable-long-section-names"
+LFCYG64="-fwhole-program -Wl,--nxcompat,--dynamicbase,--tsaware,--disable-long-section-names,--high-entropy-va"
+LFWIN64="-fwhole-program -lws2_32 -Wl,--nxcompat,--dynamicbase,--tsaware,--disable-long-section-names,--high-entropy-va"
MAKEFLAGS="-j$NUMCPU -B"
REUSEFLAGS="-j$NUMCPU"
-make $MAKEFLAGS cygkms32.dll FEATURES=minimum THREADS=1 DLL_NAME=cygkms32.dll DNS_PARSER=internal CC=i686-pc-cygwin-gcc.exe CFLAGS="$CF -flto=jobserver -fvisibility=hidden" PLATFORMFLAGS="$PF32" LDFLAGS="$LFCYG32"
-make $MAKEFLAGS cygkms64.dll FEATURES=minimum THREADS=1 DLL_NAME=cygkms64.dll DNS_PARSER=internal CC=x86_64-pc-cygwin-gcc.exe CFLAGS="$CF -flto=jobserver -fvisibility=hidden" PLATFORMFLAGS="$PF64" LDFLAGS="$LFCYG64"
-make $MAKEFLAGS all vlmcsdmulti-cygwin-x86 THREADS=1 DNS_PARSER=internal CLIENT_NAME=vlmcs-cygwin-x86 PROGRAM_NAME=vlmcsd-cygwin-x86 MULTI_NAME=vlmcsdmulti-cygwin-x86 CC=i686-pc-cygwin-gcc.exe CFLAGS="$CF" PLATFORMFLAGS="$PF32" LDFLAGS="$LFCYG32"
-make $MAKEFLAGS all vlmcsdmulti-cygwin-x64 THREADS=1 DNS_PARSER=internal CLIENT_NAME=vlmcs-cygwin-x64 PROGRAM_NAME=vlmcsd-cygwin-x64 MULTI_NAME=vlmcsdmulti-cygwin-x64 CC=x86_64-pc-cygwin-gcc.exe CFLAGS="$CF" PLATFORMFLAGS="$PF64" LDFLAGS="$LFCYG64"
+make $MAKEFLAGS cygkms32.dll FEATURES=minimum THREADS=1 DLL_NAME=cygkms32.dll DNS_PARSER=internal CC=i686-pc-cygwin-gcc.exe CFLAGS="$CF -flto=jobserver -fvisibility=hidden" PLATFORMFLAGS="$PF32" LDFLAGS="$LFCYG32 -Wl,--no-seh"
+make $MAKEFLAGS cygkms64.dll FEATURES=minimum THREADS=1 DLL_NAME=cygkms64.dll DNS_PARSER=internal CC=x86_64-pc-cygwin-gcc.exe CFLAGS="$CF -flto=jobserver -fvisibility=hidden" PLATFORMFLAGS="$PF64" LDFLAGS="$LFCYG64 -Wl,--no-seh"
+make $MAKEFLAGS all vlmcsdmulti-cygwin-x86 THREADS=1 DNS_PARSER=internal CLIENT_NAME=vlmcs-cygwin-x86 PROGRAM_NAME=vlmcsd-cygwin-x86 MULTI_NAME=vlmcsdmulti-cygwin-x86 CC=i686-pc-cygwin-gcc.exe CFLAGS="$CF" PLATFORMFLAGS="$PF32" LDFLAGS="$LFCYG32 -Wl,--no-seh"
+make $MAKEFLAGS all vlmcsdmulti-cygwin-x64 THREADS=1 DNS_PARSER=internal CLIENT_NAME=vlmcs-cygwin-x64 PROGRAM_NAME=vlmcsd-cygwin-x64 MULTI_NAME=vlmcsdmulti-cygwin-x64 CC=x86_64-pc-cygwin-gcc.exe CFLAGS="$CF" PLATFORMFLAGS="$PF64" LDFLAGS="$LFCYG64 -Wl,--no-seh"
make $MAKEFLAGS MSRPC=1 THREADS=1 DNS_PARSER=internal CLIENT_NAME=vlmcs-cygwin-msrpc-x86 PROGRAM_NAME=vlmcsd-cygwin-msrpc-x86 MULTI_NAME=vlmcsdmulti-cygwin-msrpc-x86 CC=i686-pc-cygwin-gcc.exe CFLAGS="$CF -fasynchronous-unwind-tables" PLATFORMFLAGS="$PF32" LDFLAGS="$LFCYG32"
make $MAKEFLAGS MSRPC=1 THREADS=1 DNS_PARSER=internal CLIENT_NAME=vlmcs-cygwin-msrpc-x64 PROGRAM_NAME=vlmcsd-cygwin-msrpc-x64 MULTI_NAME=vlmcsdmulti-cygwin-msrpc-x64 CC=x86_64-pc-cygwin-gcc.exe CFLAGS="$CFMSRPC" PLATFORMFLAGS="$PF64" LDFLAGS="$LFCYG64"
unset CAT
@@ -34,19 +34,24 @@ make $MAKEFLAGS THREADS=1 MSRPC=1 DNS_PARSER=internal CLIENT_NAME=vlmcs-cygwin-m
export CAT=2
-make $MAKEFLAGS libkms32.dll CRYPTO=windows FEATURES=minimum THREADS=1 DLL_NAME=libkms32.dll CC=i686-w64-MingW32-gcc.exe CFLAGS="$CF -flto=jobserver -fvisibility=hidden" PLATFORMFLAGS="$PF32" LDFLAGS="-static-libgcc $LFWIN32"
-make $MAKEFLAGS libkms64.dll CRYPTO=windows FEATURES=minimum THREADS=1 DLL_NAME=libkms64.dll CC=x86_64-w64-MingW32-gcc.exe CFLAGS="$CF -flto=jobserver -fvisibility=hidden" PLATFORMFLAGS="$PF64" LDFLAGS="-static-libgcc $LFWIN64"
-make $MAKEFLAGS all vlmcsdmulti-Windows-x86 THREADS=1 CRYPTO=windows CLIENT_NAME=vlmcs-Windows-x86 PROGRAM_NAME=vlmcsd-Windows-x86 MULTI_NAME=vlmcsdmulti-Windows-x86 CC=i686-w64-MingW32-gcc.exe CFLAGS="$CF" PLATFORMFLAGS="$PF32" LDFLAGS="$LFWIN32"
-make $MAKEFLAGS all vlmcsdmulti-Windows-x64 THREADS=1 CRYPTO=windows CLIENT_NAME=vlmcs-Windows-x64 PROGRAM_NAME=vlmcsd-Windows-x64 MULTI_NAME=vlmcsdmulti-Windows-x64 CC=x86_64-w64-MingW32-gcc.exe CFLAGS="$CF" PLATFORMFLAGS="$PF64" LDFLAGS="$LFWIN64"
-make -Bj MSRPC=1 CRYPTO=windows CLIENT_NAME=vlmcs-Windows-msrpc-x86 PROGRAM_NAME=vlmcsd-Windows-msrpc-x86 MULTI_NAME=vlmcsdmulti-Windows-msrpc-x86 CC=i686-w64-MingW32-gcc.exe CFLAGS="$CFMSRPC" PLATFORMFLAGS="$PF32" LDFLAGS="-Wl,--nxcompat,--dynamicbase,--tsaware,--large-address-aware"
-make $MAKEFLAGS THREADS=1 MSRPC=1 CRYPTO=windows CLIENT_NAME=vlmcs-Windows-msrpc-x64 PROGRAM_NAME=vlmcsd-Windows-msrpc-x64 MULTI_NAME=vlmcsdmulti-Windows-msrpc-x64 CC=x86_64-w64-MingW32-gcc.exe CFLAGS="$CFMSRPC" PLATFORMFLAGS="$PF64" LDFLAGS="$LFCYG64"
-unset CAT
-make $MAKEFLAGS vlmcsdmulti-Windows-msrpc-x86 THREADS=1 MSRPC=1 CRYPTO=windows MULTI_NAME=vlmcsdmulti-Windows-msrpc-x86 CC=i686-w64-MingW32-gcc.exe CFLAGS="$CFMSRPC" PLATFORMFLAGS="$PF32" LDFLAGS="-Wl,--nxcompat,--dynamicbase,--tsaware,--large-address-aware"
-make $MAKEFLAGS vlmcsdmulti-Windows-msrpc-x64 THREADS=1 MSRPC=1 CRYPTO=windows MULTI_NAME=vlmcsdmulti-Windows-msrpc-x64 CC=x86_64-w64-MingW32-gcc.exe CFLAGS="$CFMSRPC" PLATFORMFLAGS="$PF64" LDFLAGS="$LFCYG64"
+#make $MAKEFLAGS libkms32.dll CRYPTO=windows FEATURES=minimum THREADS=1 DLL_NAME=libkms32.dll CC=i686-w64-MingW32-gcc.exe CFLAGS="$CF -flto=jobserver -fvisibility=hidden" PLATFORMFLAGS="$PF32" LDFLAGS="-static-libgcc $LFWIN32"
+#make $MAKEFLAGS libkms64.dll CRYPTO=windows FEATURES=minimum THREADS=1 DLL_NAME=libkms64.dll CC=x86_64-w64-MingW32-gcc.exe CFLAGS="$CF -flto=jobserver -fvisibility=hidden" PLATFORMFLAGS="$PF64" LDFLAGS="-static-libgcc $LFWIN64"
+#make $MAKEFLAGS all vlmcsdmulti-Windows-x86 THREADS=1 CRYPTO=windows CLIENT_NAME=vlmcs-Windows-x86 PROGRAM_NAME=vlmcsd-Windows-x86 MULTI_NAME=vlmcsdmulti-Windows-x86 CC=i686-w64-MingW32-gcc.exe CFLAGS="$CF" PLATFORMFLAGS="$PF32" LDFLAGS="$LFWIN32"
+#make $MAKEFLAGS all vlmcsdmulti-Windows-x64 THREADS=1 CRYPTO=windows CLIENT_NAME=vlmcs-Windows-x64 PROGRAM_NAME=vlmcsd-Windows-x64 MULTI_NAME=vlmcsdmulti-Windows-x64 CC=x86_64-w64-MingW32-gcc.exe CFLAGS="$CF" PLATFORMFLAGS="$PF64" LDFLAGS="$LFWIN64"
+#make -Bj MSRPC=1 CRYPTO=windows CLIENT_NAME=vlmcs-Windows-msrpc-x86 PROGRAM_NAME=vlmcsd-Windows-msrpc-x86 MULTI_NAME=vlmcsdmulti-Windows-msrpc-x86 CC=i686-w64-MingW32-gcc.exe CFLAGS="$CFMSRPC" PLATFORMFLAGS="$PF32" LDFLAGS="-Wl,--nxcompat,--dynamicbase,--tsaware,--large-address-aware"
+#make $MAKEFLAGS THREADS=1 MSRPC=1 CRYPTO=windows CLIENT_NAME=vlmcs-Windows-msrpc-x64 PROGRAM_NAME=vlmcsd-Windows-msrpc-x64 MULTI_NAME=vlmcsdmulti-Windows-msrpc-x64 CC=x86_64-w64-MingW32-gcc.exe CFLAGS="$CFMSRPC" PLATFORMFLAGS="$PF64" LDFLAGS="$LFCYG64"
+#unset CAT
+#make $MAKEFLAGS vlmcsdmulti-Windows-msrpc-x86 THREADS=1 MSRPC=1 CRYPTO=windows MULTI_NAME=vlmcsdmulti-Windows-msrpc-x86 CC=i686-w64-MingW32-gcc.exe CFLAGS="$CFMSRPC" PLATFORMFLAGS="$PF32" LDFLAGS="-Wl,--nxcompat,--dynamicbase,--tsaware,--large-address-aware"
+#make $MAKEFLAGS vlmcsdmulti-Windows-msrpc-x64 THREADS=1 MSRPC=1 CRYPTO=windows MULTI_NAME=vlmcsdmulti-Windows-msrpc-x64 CC=x86_64-w64-MingW32-gcc.exe CFLAGS="$CFMSRPC" PLATFORMFLAGS="$PF64" LDFLAGS="$LFCYG64"
export CAT=2
rm -f *_all.* *.o 2> /dev/null &
+echo ""
+echo "Copying MingW binaries from distribution server"
+
+scp -p root@ubuntu64:x/binaries/Windows/intel/* .
+
echo ""
echo "Installing binaries"
diff --git a/network.c b/network.c
index 69cdcbe..a9a3e48 100644
--- a/network.c
+++ b/network.c
@@ -207,8 +207,88 @@ SOCKET connectToAddress(const char *const addr, const int AddressFamily, int_fas
return s;
}
+// fix for lame tomato toolchain
+# if !defined(IPV6_V6ONLY) && defined(__linux__)
+# define IPV6_V6ONLY (26)
+# endif // !defined(IPV6_V6ONLY) && defined(__linux__)
+
#ifndef NO_SOCKETS
+#ifdef SIMPLE_SOCKETS
+
+static int_fast8_t allowSocketReuse(SOCKET s)
+{
+# if !defined(_WIN32) && !defined(__CYGWIN__)
+ BOOL socketOption = TRUE;
+# else // _WIN32
+ BOOL socketOption = FALSE;
+# endif // _WIN32
+
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (sockopt_t)&socketOption, sizeof(socketOption)))
+ {
+# ifdef _PEDANTIC
+ printerrorf("Warning: %s does not support socket option SO_REUSEADDR: %s\n", ipstr, vlmcsd_strerror(socket_errno));
+# endif // _PEDANTIC
+ }
+
+ return 0;
+}
+
+
+int listenOnAllAddresses()
+{
+ uint32_t port_listen;
+
+ if (!stringToInt(defaultport, 1, 65535, &port_listen))
+ {
+ printerrorf("Fatal: Port must be numeric between 1 and 65535.\n");
+ exit(!0);
+ }
+
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_port = BE16((uint16_t)port_listen);
+ addr.sin6_addr = in6addr_any;
+ BOOL v6only = FALSE;
+
+ s_server = socket(AF_INET6, SOCK_STREAM, 0);
+
+ if (s_server == INVALID_SOCKET
+ || allowSocketReuse(s_server)
+ || setsockopt(s_server, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_t)&v6only, sizeof(v6only))
+ || bind(s_server, (struct sockaddr *)&addr, sizeof(addr))
+ || listen(s_server, SOMAXCONN) )
+ {
+ socketclose(s_server);
+ struct sockaddr_in addr = {
+ .sin_family = AF_INET,
+ .sin_port = BE16((uint16_t)port_listen),
+ };
+
+ addr.sin_addr.s_addr = BE32(INADDR_ANY);
+ s_server = socket(AF_INET, SOCK_STREAM, 0);
+
+ if ( s_server == INVALID_SOCKET
+ || allowSocketReuse(s_server)
+ || bind(s_server, (struct sockaddr *)&addr, sizeof(addr))
+ || listen(s_server, SOMAXCONN) )
+ {
+ int error = socket_errno;
+ printerrorf("Fatal: Cannot bind to TCP port %u: %s\n", port_listen, vlmcsd_strerror(error));
+ return error;
+ }
+ }
+
+ #ifndef NO_LOG
+ logger("Listening on TCP port %u\n", port_listen);
+ #endif // NO_LOG
+
+ return 0;
+}
+
+#else // !SIMPLE_SOCKETS
+
// Create a Listening socket for addrinfo sa and return socket s
// szHost and szPort are for logging only
@@ -249,20 +329,67 @@ static int listenOnAddress(const struct addrinfo *const ai, SOCKET *s)
BOOL socketOption = TRUE;
- // fix for lame tomato toolchain
-# ifndef IPV6_V6ONLY
-# ifdef __linux__
-# define IPV6_V6ONLY (26)
-# endif // __linux__
-# endif // IPV6_V6ONLY
-
# ifdef IPV6_V6ONLY
- if (ai->ai_family == AF_INET6) setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_t)&socketOption, sizeof(socketOption));
+ if (ai->ai_family == AF_INET6 && setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_t)&socketOption, sizeof(socketOption)))
+ {
+# ifdef _PEDANTIC
+# if defined(_WIN32) || defined(__CYGWIN__)
+// if (IsWindowsVistaOrGreater()) //Doesn't work with older version of MingW32-w64 toolchain
+ if ((GetVersion() & 0xff) > 5)
+# endif // _WIN32
+ printerrorf("Warning: %s does not support socket option IPV6_V6ONLY: %s\n", ipstr, vlmcsd_strerror(socket_errno));
+# endif // _PEDANTIC
+ }
# endif
# ifndef _WIN32
- setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (sockopt_t)&socketOption, sizeof(socketOption));
-# endif
+ if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (sockopt_t)&socketOption, sizeof(socketOption)))
+ {
+# ifdef _PEDANTIC
+ printerrorf("Warning: %s does not support socket option SO_REUSEADDR: %s\n", ipstr, vlmcsd_strerror(socket_errno));
+# endif // _PEDANTIC
+ }
+# endif // _WIN32
+
+# if HAVE_FREEBIND
+# if (defined(IP_NONLOCALOK) || __FreeBSD_kernel__ || __FreeBSD__) && !defined(IPV6_BINDANY)
+# define IPV6_BINDANY 64
+# endif // (defined(IP_NONLOCALOK) || __FreeBSD_kernel__ || __FreeBSD__) && !defined(IPV6_BINDANY)
+
+ if (freebind)
+ {
+# if defined(IP_FREEBIND) // Linux
+ if (setsockopt(*s, IPPROTO_IP, IP_FREEBIND, (sockopt_t)&socketOption, sizeof(socketOption)))
+ {
+ printerrorf("Warning: Cannot use FREEBIND on %s: %s\n", ipstr, vlmcsd_strerror(socket_errno));
+ }
+# endif // defined(IP_FREEBIND)
+
+# if defined(IP_BINDANY) // FreeBSD IPv4
+ if (ai->ai_family == AF_INET && setsockopt(*s, IPPROTO_IP, IP_BINDANY, (sockopt_t)&socketOption, sizeof(socketOption)))
+ {
+ printerrorf("Warning: Cannot use BINDANY on %s: %s\n", ipstr, vlmcsd_strerror(socket_errno));
+ }
+# endif // defined(IP_BINDANY)
+
+# if defined(IPV6_BINDANY) // FreeBSD IPv6
+ if (ai->ai_family == AF_INET6 && setsockopt(*s, IPPROTO_IP, IPV6_BINDANY, (sockopt_t)&socketOption, sizeof(socketOption)))
+ {
+# ifdef _PEDANTIC // FreeBSD defines the symbol but doesn't have BINDANY in IPv6 (Kame stack doesn't have it)
+ printerrorf("Warning: Cannot use BINDANY on %s: %s\n", ipstr, vlmcsd_strerror(socket_errno));
+# endif
+ }
+# endif // defined(IPV6_BINDANY)
+
+# if defined(IP_NONLOCALOK) && !defined(IP_BINDANY) // FreeBSD with GNU userspace IPv4
+ if (ai->ai_family == AF_INET && setsockopt(*s, IPPROTO_IP, IP_NONLOCALOK, (sockopt_t)&socketOption, sizeof(socketOption)))
+ {
+ printerrorf("Warning: Cannot use BINDANY on %s: %s\n", ipstr, vlmcsd_strerror(socket_errno));
+ }
+# endif // defined(IP_NONLOCALOK) && !defined(IP_BINDANY)
+ }
+
+# endif // HAVE_FREEBIND
if (bind(*s, ai->ai_addr, ai->ai_addrlen) || listen(*s, SOMAXCONN))
{
@@ -279,7 +406,6 @@ static int listenOnAddress(const struct addrinfo *const ai, SOCKET *s)
return 0;
}
-
// Adds a listening socket for an address string,
// e.g. 127.0.0.1:1688 or [2001:db8:dead:beef::1]:1688
BOOL addListeningSocket(const char *const addr)
@@ -366,10 +492,18 @@ static SOCKET network_accept_any()
else
return accept(sock, NULL, NULL);
}
+#endif // !SIMPLE_SOCKETS
void closeAllListeningSockets()
{
+# ifdef SIMPLE_SOCKETS
+
+ shutdown(s_server, VLMCSD_SHUT_RDWR);
+ socketclose(s_server);
+
+# else // !SIMPLE_SOCKETS
+
int i;
for (i = 0; i < numsockets; i++)
@@ -377,6 +511,8 @@ void closeAllListeningSockets()
shutdown(SocketList[i], VLMCSD_SHUT_RDWR);
socketclose(SocketList[i]);
}
+
+ #endif // !SIMPLE_SOCKETS
}
#endif // NO_SOCKETS
@@ -641,13 +777,16 @@ int runServer()
return 0;
}
- // Standalone mode
for (;;)
{
int error;
SOCKET s_client;
+ #ifdef SIMPLE_SOCKETS
+ if ( (s_client = accept(s_server, NULL, NULL)) == INVALID_SOCKET )
+ #else // Standalone mode fully featured sockets
if ( (s_client = network_accept_any()) == INVALID_SOCKET )
+ #endif // Standalone mode fully featured sockets
{
error = socket_errno;
diff --git a/network.h b/network.h
index 7c56038..30662b9 100644
--- a/network.h
+++ b/network.h
@@ -22,6 +22,9 @@ int_fast8_t sendrecv(SOCKET sock, BYTE *data, int len, int_fast8_t do_send);
#ifndef NO_SOCKETS
void closeAllListeningSockets();
+#ifdef SIMPLE_SOCKETS
+int listenOnAllAddresses();
+#endif // SIMPLE_SOCKETS
BOOL addListeningSocket(const char *const addr);
__pure int_fast8_t checkProtocolStack(const int addressfamily);
diff --git a/output.c b/output.c
index 22599ed..bc44ffe 100644
--- a/output.c
+++ b/output.c
@@ -94,25 +94,35 @@ int logger(const char *const fmt, ...)
// Output to stderr if it is available or to log otherwise (e.g. if running as daemon/service)
void printerrorf(const char *const fmt, ...)
{
+ int error = errno;
va_list arglist;
va_start(arglist, fmt);
- #ifndef NO_LOG
- #ifdef _NTSERVICE
+# ifdef IS_LIBRARY
+
+ snprintf(ErrorMessage, MESSAGE_BUFFER_SIZE, fmt, arglist);
+
+# else // !IS_LIBRARY
+
+# ifndef NO_LOG
+# ifdef _NTSERVICE
if (InetdMode || IsNTService)
- #else // !_NTSERVICE
+# else // !_NTSERVICE
if (InetdMode)
- #endif // NTSERVIICE
+# endif // NTSERVIICE
vlogger(fmt, arglist);
else
- #endif //NO_LOG
+# endif //NO_LOG
+
+# endif // IS_LIBRARY
{
vfprintf(stderr, fmt, arglist);
fflush(stderr);
}
va_end(arglist);
+ errno = error;
}
@@ -130,10 +140,12 @@ int errorout(const char* fmt, ...)
}
+#ifndef NO_VERBOSE_LOG
static const char *LicenseStatusText[] =
{
"Unlicensed", "Licensed", "OOB grace", "OOT grace", "Non-Genuine", "Notification", "Extended grace"
};
+#endif // NO_VERBOSE_LOG
void uuid2StringLE(const GUID *const guid, char *const string)
@@ -152,7 +164,7 @@ void uuid2StringLE(const GUID *const guid, char *const string)
);
}
-
+#ifndef NO_VERBOSE_LOG
void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p)
{
char guidBuffer[GUID_STRING_LENGTH + 1];
@@ -208,7 +220,6 @@ 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)
{
char guidBuffer[GUID_STRING_LENGTH + 1];
@@ -237,4 +248,374 @@ void logResponseVerbose(const char *const ePID, const BYTE *const hwid, const RE
p("Renewal interval policy : %u\n", (uint32_t)LE32(response->VLRenewalInterval));
p("Activation interval policy : %u\n", (uint32_t)LE32(response->VLActivationInterval));
}
+#endif // NO_VERBOSE_LOG
+
+#ifndef NO_VERSION_INFORMATION
+void printPlatform()
+{
+ int testNumber = 0x1234;
+
+# ifdef VLMCSD_COMPILER
+ printf
+ (
+ "Compiler: %s\n", VLMCSD_COMPILER
+# ifdef __VERSION__
+ " " __VERSION__
+# endif // __VERSION__
+ );
+# endif // VLMCSD_COMPILER
+
+ printf
+ (
+ "Intended platform:%s %s\n", ""
+
+# if __i386__ || _M_IX86
+ " Intel x86"
+# endif
+
+# if __x86_64__ || __amd64__ || _M_X64 || _M_AMD64
+ " Intel x86_64"
+# endif
+
+# if _M_ARM || __arm__
+ " ARM"
+# endif
+
+# if __thumb__
+ " thumb"
+# endif
+
+# if __aarch64__
+ " ARM64"
+# endif
+
+# if __hppa__
+ " HP/PA RISC"
+# endif
+
+# if __ia64__
+ " Intel Itanium"
+# endif
+
+# if __mips__
+ " MIPS"
+# endif
+
+# if defined(_MIPS_ARCH)
+ " " _MIPS_ARCH
+# endif
+
+# if __mips16
+ " mips16"
+# endif
+
+# if __mips_micromips
+ " micromips"
+# endif
+
+# if __ppc__ || __powerpc__
+ " PowerPC"
+# endif
+
+# if __powerpc64__ || __ppc64__
+ " PowerPC64"
+# endif
+
+# if __sparc__
+ " SPARC"
+# endif
+
+# if defined(__s390__) && !defined(__zarch__) && !defined(__s390x__)
+ " IBM S/390"
+# endif
+
+# if __zarch__ || __s390x__
+ " IBM z/Arch (S/390x)"
+# endif
+
+# if __m68k__
+ " Motorola 68k"
+# endif
+
+# if __ANDROID__
+ " Android"
+# endif
+
+# if __ANDROID_API__
+ " (API level " ANDROID_API_LEVEL ")"
+# endif
+
+# if __FreeBSD__ || __FreeBSD_kernel__
+ " FreeBSD"
+# endif
+
+# if __NetBSD__
+ " NetBSD"
+# endif
+
+# if __OpenBSD__
+ " OpenBSD"
+# endif
+
+# if __DragonFly__
+ " DragonFly BSD"
+# endif
+
+# if defined(__CYGWIN__) && !defined(_WIN64)
+ " Cygwin32"
+# endif
+
+# if defined(__CYGWIN__) && defined(_WIN64)
+ " Cygwin64"
+# endif
+
+# if __GNU__
+ " GNU"
+# endif
+
+# if __gnu_hurd__
+ " Hurd"
+# endif
+
+# if __MACH__
+ " Mach"
+# endif
+
+# if __linux__
+ " Linux"
+# endif
+
+# if __APPLE__ && __MACH__
+ " Darwin"
+# endif
+
+# if __minix__
+ " Minix"
+# endif
+
+# if __QNX__
+ " QNX"
+# endif
+
+# if __svr4__ || __SVR4
+ " SYSV R4"
+# endif
+
+# if (defined(__sun__) || defined(sun) || defined(__sun)) && (defined(__SVR4) || defined(__svr4__))
+ " Solaris"
+# endif
+
+# if (defined(__sun__) || defined(sun) || defined(__sun)) && !defined(__SVR4) && !defined(__svr4__)
+ " SunOS"
+# endif
+
+# if defined(_WIN32) && !defined(_WIN64)
+ " Windows32"
+# endif
+
+# if defined(_WIN32) && defined(_WIN64)
+ " Windows64"
+# endif
+
+# if __MVS__ || __TOS_MVS__
+ " z/OS"
+# endif
+
+# if defined(__GLIBC__) && !defined(__UCLIBC__)
+ " glibc"
+# endif
+
+# if __UCLIBC__
+ " uclibc"
+# endif
+
+# if defined(__linux__) && !defined(__GLIBC__) && !defined(__UCLIBC__) && !defined(__ANDROID__) && !defined(__BIONIC__)
+ " musl"
+# endif
+
+//# if _MIPSEL || __MIPSEL__ || __ARMEL__ || __THUMBEL__
+// " little-endian"
+//# endif
+//
+//# if _MIPSEB || __MIPSEB__ || __ARMEB__ || __THUMBEB__
+// " big-endian"
+//# endif
+
+# if __PIE__ || __pie__
+ " PIE"
+# endif
+ ,
+ *((uint8_t*)&testNumber) == 0x34 ? "little-endian" : "big-endian"
+ );
+
+}
+
+
+void printCommonFlags()
+{
+ printf
+ (
+ "Common flags:%s\n",""
+
+# ifdef NO_EXTENDED_PRODUCT_LIST
+ " NO_EXTENDED_PRODUCT_LIST"
+# endif // NO_EXTENDED_PRODUCT_LIST
+
+# ifdef NO_BASIC_PRODUCT_LIST
+ " NO_BASIC_PRODUCT_LIST"
+# endif // NO_BASIC_PRODUCT_LIST
+
+# ifdef USE_MSRPC
+ " USE_MSRPC"
+# endif // USE_MSRPC
+
+# ifdef _CRYPTO_OPENSSL
+ " _CRYPTO_OPENSSL"
+# endif // _CRYPTO_OPENSSL
+
+# ifdef _CRYPTO_POLARSSL
+ " _CRYPTO_POLARSSL"
+# endif // _CRYPTO_POLARSSL
+
+# ifdef _CRYPTO_WINDOWS
+ " _CRYPTO_WINDOWS"
+# endif // _CRYPTO_WINDOWS
+
+# if defined(_OPENSSL_SOFTWARE) && defined(_CRYPTO_OPENSSL)
+ " _OPENSSL_SOFTWARE"
+# endif // _OPENSSL_SOFTWARE
+
+# if defined(_USE_AES_FROM_OPENSSL) && defined(_CRYPTO_OPENSSL)
+ " _USE_AES_FROM_OPENSSL"
+# endif // _USE_AES_FROM_OPENSSL
+
+# if defined(_OPENSSL_NO_HMAC) && defined(_CRYPTO_OPENSSL)
+ " OPENSSL_HMAC=0"
+# endif // _OPENSSL_NO_HMAC
+
+# ifdef _PEDANTIC
+ " _PEDANTIC"
+# endif // _PEDANTIC
+
+# ifdef INCLUDE_BETAS
+ " INCLUDE_BETAS"
+# endif // INCLUDE_BETAS
+
+# if __minix__ || defined(NO_TIMEOUT)
+ " NO_TIMEOUT=1"
+# endif // __minix__ || defined(NO_TIMEOUT)
+ );
+}
+
+
+void printClientFlags()
+{
+ printf
+ (
+ "vlmcs flags:%s\n",""
+
+# ifdef NO_DNS
+ " NO_DNS=1"
+# endif
+
+# if !defined(NO_DNS)
+# if defined(DNS_PARSER_INTERNAL) && !defined(_WIN32)
+ " DNS_PARSER=internal"
+# else // !defined(DNS_PARSER_INTERNAL) || defined(_WIN32)
+ " DNS_PARSER=OS"
+# endif // !defined(DNS_PARSER_INTERNAL) || defined(_WIN32)
+# endif // !defined(NO_DNS)
+
+# if defined(DISPLAY_WIDTH)
+ " TERMINAL_WIDTH=" DISPLAY_WIDTH
+# endif
+ );
+}
+
+
+void printServerFlags()
+{
+ printf
+ (
+ "vlmcsd flags:%s\n",""
+
+# ifdef NO_LOG
+ " NO_LOG"
+# endif // NO_LOG
+
+# ifdef NO_RANDOM_EPID
+ " NO_RANDOM_EPID"
+# endif // NO_RANDOM_EPID
+
+# ifdef NO_INI_FILE
+ " NO_INI_FILE"
+# endif // NO_INI_FILE
+
+# if !defined(NO_INI_FILE) && defined(INI_FILE)
+ " INI=" INI_FILE
+# endif // !defined(NO_INI_FILE)
+
+# ifdef NO_PID_FILE
+ " NO_PID_FILE"
+# endif // NO_PID_FILE
+
+# ifdef NO_USER_SWITCH
+ " NO_USER_SWITCH"
+# endif // NO_USER_SWITCH
+
+# ifdef NO_HELP
+ " NO_HELP"
+# endif // NO_HELP
+
+# ifdef NO_CUSTOM_INTERVALS
+ " NO_CUSTOM_INTERVALS"
+# endif // NO_CUSTOM_INTERVALS
+
+# ifdef NO_SOCKETS
+ " NO_SOCKETS"
+# endif // NO_SOCKETS
+
+# ifdef NO_CL_PIDS
+ " NO_CL_PIDS"
+# endif // NO_CL_PIDS
+
+# ifdef NO_LIMIT
+ " NO_LIMIT"
+# endif // NO_LIMIT
+
+# ifdef NO_SIGHUP
+ " NO_SIGHUP"
+# endif // NO_SIGHUP
+
+# ifdef NO_PROCFS
+ " NOPROCFS=1"
+# endif // NO_PROCFS
+
+# ifdef USE_THREADS
+ " THREADS=1"
+# endif // USE_THREADS
+
+# ifdef USE_AUXV
+ " AUXV=1"
+# endif // USE_AUXV
+
+# if defined(CHILD_HANDLER) || __minix__
+ " CHILD_HANDLER=1"
+# endif // defined(CHILD_HANDLER) || __minix__
+
+# if !defined(NO_SOCKETS) && defined(SIMPLE_SOCKETS)
+ " SIMPLE_SOCKETS"
+# endif // !defined(NO_SOCKETS) && defined(SIMPLE_SOCKETS)
+
+# if (_WIN32 || __CYGWIN__) && (!defined(USE_MSRPC) || defined(SUPPORT_WINE))
+ " SUPPORT_WINE"
+# endif // (_WIN32 || __CYGWIN__) && (!defined(USE_MSRPC) || defined(SUPPORT_WINE))
+
+# if !HAVE_FREEBIND
+ " NO_FREEBIND"
+# endif //!HAVE_FREEBIND
+
+ );
+}
+#endif // NO_VERSION_INFORMATION
diff --git a/output.h b/output.h
index 77b3783..e08e9e2 100644
--- a/output.h
+++ b/output.h
@@ -6,6 +6,7 @@
#endif // CONFIG
#include CONFIG
+#include
#include "kms.h"
typedef int (*PRINTFUNC)(const char *const fmt, ...);
@@ -15,6 +16,13 @@ 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);
+#ifndef NO_VERSION_INFORMATION
+void printPlatform();
+void printCommonFlags();
+void printServerFlags();
+void printClientFlags();
+#endif // NO_VERSION_INFORMATION
+
#ifndef NO_LOG
int logger(const char *const fmt, ...);
#endif //NO_LOG
diff --git a/shared_globals.c b/shared_globals.c
index f7f3265..1f91da8 100644
--- a/shared_globals.c
+++ b/shared_globals.c
@@ -51,10 +51,14 @@ int_fast8_t logverbose = 0;
#endif // NO_LOG
#ifndef NO_SOCKETS
+#ifndef _WIN32
int_fast8_t nodaemon = 0;
+#endif // _WIN32
int_fast8_t InetdMode = 0;
#else
+#ifndef _WIN32
int_fast8_t nodaemon = 1;
+#endif // _WIN32
int_fast8_t InetdMode = 1;
#endif
@@ -64,8 +68,12 @@ uint16_t Lcid = 0;
#endif
#ifndef NO_SOCKETS
+#ifdef SIMPLE_SOCKETS
+SOCKET s_server;
+#else
SOCKET *SocketList;
int numsockets = 0;
+#endif
#if !defined(NO_LIMIT) && !__minix__
#ifndef _WIN32 // Posix
@@ -92,6 +100,10 @@ CRITICAL_SECTION logmutex;
#endif // USE_THREADS
#endif // NO_LOG
+#if HAVE_FREEBIND
+int_fast8_t freebind = FALSE;
+#endif // HAVE_FREEBIND
+
diff --git a/shared_globals.h b/shared_globals.h
index a59618c..7e56946 100644
--- a/shared_globals.h
+++ b/shared_globals.h
@@ -74,10 +74,16 @@ extern const char *const Version;
#define UINT_MAX 4294967295
#endif
+#ifdef IS_LIBRARY
+#define MESSAGE_BUFFER_SIZE 256
+EXTERNC __declspec(EXTERNAL) extern char ErrorMessage[MESSAGE_BUFFER_SIZE];
+#endif // IS_LIBRARY
extern int global_argc, multi_argc;
extern CARGV global_argv, multi_argv;
+#ifndef _WIN32
extern int_fast8_t nodaemon;
+#endif // _WIN32
extern DWORD VLActivationInterval;
extern DWORD VLRenewalInterval;
extern int_fast8_t DisconnectImmediately;
@@ -122,8 +128,12 @@ extern uint16_t Lcid;
#endif
#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
+#if defined(SIMPLE_SOCKETS)
+extern SOCKET s_server;
+#else // !defined(SIMPLE_SOCKETS)
extern SOCKET *SocketList;
extern int numsockets;
+#endif // !defined(SIMPLE_SOCKETS)
#if !defined(NO_LIMIT) && !__minix__
@@ -152,5 +162,9 @@ extern CRITICAL_SECTION logmutex;
#endif // USE_THREADS
#endif // NO_LOG
+#if HAVE_FREEBIND
+extern int_fast8_t freebind;
+#endif // HAVE_FREEBIND
+
#endif // INCLUDED_SHARED_GLOBALS_H
diff --git a/strip_binaries b/strip_binaries
new file mode 100755
index 0000000..992522e
--- /dev/null
+++ b/strip_binaries
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+find binaries -xdev -name 'vlmcs*' ! -name '*-NetBSD-*' ! -name '*-Windows-*' ! -name '*-cygwin-*' ! -name '*-MacOSX-*' ! -name '*-iOS-*' -exec sstrip -z {} \;
diff --git a/types.h b/types.h
index 4948996..7f09709 100644
--- a/types.h
+++ b/types.h
@@ -6,13 +6,41 @@
#endif // CONFIG
#include CONFIG
+#define ANDROID_API_LEVEL ANDROID_HELPER1(__ANDROID_API__)
+#define ANDROID_HELPER1(s) ANDROID_HELPER2(s)
+#define ANDROID_HELPER2(s) #s
+
+#if !defined(_WIN32) && !__CYGWIN__
+#define __declspec(x) __attribute__((__visibility__("default")))
+#endif
+
+#if !defined(EXTERNAL)
+#define EXTERNAL dllimport
+#endif
+
+#ifdef __cplusplus
+#define EXTERNC extern "C"
+#else
+#define EXTERNC
+#endif
+
#include
#include
#include
-//#ifdef __sun__
-//#include
-//#endif
+#ifdef __ANDROID__
+#include
+#endif // __ANDROID__
+
+#ifndef _WIN32
+#include
+#endif // _WIN32
+
+
+#if (IP_BINDANY || IP_FREEBIND || IPV6_BINDANY || IP_NONLOCALOK) && !defined(NO_FREEBIND) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
+#define HAVE_FREEBIND 1
+#endif
+
#ifndef alloca
#ifdef __GNUC__
#define alloca(x) __builtin_alloca(x)
@@ -156,6 +184,7 @@ typedef uint8_t ProdListIndex_t;
#endif // USE_MSRPC
#include
+//#include
typedef char* sockopt_t;
@@ -184,6 +213,7 @@ typedef char* sockopt_t;
#elif defined(__CYGWIN__)
#include
+
// Resolve conflicts between OpenSSL and MS Crypto API
#ifdef _CRYPTO_OPENSSL
#undef OCSP_RESPONSE
diff --git a/vlmcs.1 b/vlmcs.1
index dcbcf8d..b42e44a 100644
--- a/vlmcs.1
+++ b/vlmcs.1
@@ -1,5 +1,5 @@
.mso www.tmac
-.TH VLMCS 1 "February 2015" "Hotbird64" "KMS Activation Manual"
+.TH VLMCS 1 "May 2016" "Hotbird64" "KMS Activation Manual"
.LO 1
.SH NAME
@@ -11,7 +11,7 @@ vlmcs \- a client for testing and/or charging KMS servers
\fItarget\fR can be one of the following:
.RS
.PP
-\fIhostname\fR|\fIipaddress\fR[:\fItcp-port\fR] or to query a specific KMS server (example: vlmcs kms.example.com:1688).
+\fIhostname\fR|\fIipaddress\fR[:\fItcp-port\fR] to query a specific KMS server (example: vlmcs kms.example.com:1688).
.br
\fR.\fIdomain\fR to automatically detect KMS servers via DNS for \fIdomain\fR (example: vlmcs .example.com). Please note the dot before \fIdomain\fR.
.br
@@ -44,6 +44,9 @@ can also be used to "charge" a KMS server. A Microsoft KMS server sends correct
.IP "\fB-h\fR or \fB-?"
Show help.
+.IP "\fB-V\fR"
+Displays extended version information. This includes the compiler used to build vlmcs, the intended platform and flags (compile time options) to build vlmcs. If you have the source code of vlmcsd, you can type \fBmake help\fR (or \fBgmake help\fR on systems that do not use the GNU version of \fBmake\fR(1) by default) to see the meaning of those flags.
+
.IP \fB-x
Show valid
.IR application s
diff --git a/vlmcs.1.dos.txt b/vlmcs.1.dos.txt
index 33fc67b..49d84eb 100644
--- a/vlmcs.1.dos.txt
+++ b/vlmcs.1.dos.txt
@@ -11,7 +11,7 @@ SYNOPSIS
target can be one of the following:
- hostname|ipaddress[:tcp-port] or to query a specific KMS server
+ hostname|ipaddress[:tcp-port] to query a specific KMS server
(example: vlmcs kms.example.com:1688).
.domain to automatically detect KMS servers via DNS for domain
(example: vlmcs .example.com). Please note the dot before
@@ -52,6 +52,14 @@ OPTIONS
Show help.
+ -V Displays extended version information. This includes the com‐
+ piler used to build vlmcs, the intended platform and flags (com‐
+ pile time options) to build vlmcs. If you have the source code
+ of vlmcsd, you can type make help (or gmake help on systems that
+ do not use the GNU version of make(1) by default) to see the
+ meaning of those flags.
+
+
-x Show valid applications that can be used with -l.
@@ -59,44 +67,44 @@ OPTIONS
-v Be verbose. Instead of just displaying the returned ePID and the
- HwId (protocol v6 only) vlmcsd shows all details of the query
+ HwId (protocol v6 only) vlmcsd shows all details of the query
and the response.
-l application
- Request activation for a specific application. Valid applica‐
- tions can be displayed by using -x. The default application is
- Windows Vista Business. The list of available applications is
+ Request activation for a specific application. Valid applica‐
+ tions can be displayed by using -x. The default application is
+ Windows Vista Business. The list of available applications is
not complete. You may supply GUIDs with -a, -k and -s to specify
- applications that are not listed with -x. The -l option is used
+ applications that are not listed with -x. The -l option is used
as a shortcut for the most common applications.
-4, -5 and -6
- Force version 4, 5 or 6 of the KMS protocol. The default is to
+ Force version 4, 5 or 6 of the KMS protocol. The default is to
select a suitable version according to the application selected.
Plese note that some products (e.g. Office 2013) may use differ‐
ent protocols with different versions of Windows.
- -m Let the client pretend to be a virtual machine. Early versions
- of Microsoft's KMS server did not increase the client count if
- the request came from a virtual machine. Newer versions ignore
+ -m Let the client pretend to be a virtual machine. Early versions
+ of Microsoft's KMS server did not increase the client count if
+ the request came from a virtual machine. Newer versions ignore
this flag.
-d Use NetBIOS names instead of DNS names. By default vlmcsd gener‐
- ates some random DNS names for each request. If you prefer Net‐
- BIOS names, you may use -d. A real Microsoft activation client
- uses DNS names or NetBIOS depending on the client name configu‐
+ ates some random DNS names for each request. If you prefer Net‐
+ BIOS names, you may use -d. A real Microsoft activation client
+ uses DNS names or NetBIOS depending on the client name configu‐
ration. KMS servers treat the workstation name as a comment that
- affects logging only. Clients will be identified by a GUID that
- can be specified using -c. -d has no effect if you also specify
+ affects logging only. Clients will be identified by a GUID that
+ can be specified using -c. -d has no effect if you also specify
-w.
-a application-guid
- Send requests with a specific application-guid. There are cur‐
+ Send requests with a specific application-guid. There are cur‐
rently only three known valid application-guids:
@@ -105,91 +113,91 @@ OPTIONS
0ff1ce15-a989-479d-af46-f275c6370663 (Office 2013)
- A Microsoft KMS server uses these GUIDs to have seperate coun‐
- ters for the already activated clients. A client that does not
- contact the KMS server within 30 days will be deleted from the
+ A Microsoft KMS server uses these GUIDs to have seperate coun‐
+ ters for the already activated clients. A client that does not
+ contact the KMS server within 30 days will be deleted from the
database. Emulated KMS servers are always fully charged.
-k kms-guid
- Send requests with a specific kms-guid. A Microsoft KMS server
- uses these GUIDs as a product id to decide whether to grant
- activation or not. A list of current kms-guids can be found in
- kms.c (table KmsIdList). Emulated KMS servers grant activation
+ Send requests with a specific kms-guid. A Microsoft KMS server
+ uses these GUIDs as a product id to decide whether to grant
+ activation or not. A list of current kms-guids can be found in
+ kms.c (table KmsIdList). Emulated KMS servers grant activation
unconditionally and do not check the kms-guid.
-s activation-guid
- The activation-guid defines the actual product, e.g. "Windows
- 8.1 Professional WMC KMSCLIENT edition". A activation-guid maps
- 1:1 to a product key. However, neither a Microsoft KMS server
+ The activation-guid defines the actual product, e.g. "Windows
+ 8.1 Professional WMC KMSCLIENT edition". A activation-guid maps
+ 1:1 to a product key. However, neither a Microsoft KMS server
nor emulated servers check this id. The activation-guid is use‐
- ful in logging to get a specific product description like "Win‐
- dows 8.1 Professional WMC". A list of current activation-guids
+ ful in logging to get a specific product description like "Win‐
+ dows 8.1 Professional WMC". A list of current activation-guids
can be found in kms.c (table ExtendedProductList).
-n requests
- Send requests requests to the server. The default is to send at
+ Send requests requests to the server. The default is to send at
least one request and enough subsequent requests that the server
- is fully charged afterwards for the application-guid you
+ is fully charged afterwards for the application-guid you
selected (explicitly with -a or implicitly by using -l).
- -T Causes to use a new TCP connection for each request if multiple
- requests are sent with vlmcsd. This is useful when you want to
- test an emulated KMS server whether it suffers from memory
- leaks. To test for memory leaks use -n with a large number of
- requests (> 100000) and then test twice (with and without -T).
- This option may become neccessary for future versions of Micro‐
- soft's KMS server because multiple requests with different
- clients-guids for the same kms-id-guid are impossible in a real
+ -T Causes to use a new TCP connection for each request if multiple
+ requests are sent with vlmcsd. This is useful when you want to
+ test an emulated KMS server whether it suffers from memory
+ leaks. To test for memory leaks use -n with a large number of
+ requests (> 100000) and then test twice (with and without -T).
+ This option may become neccessary for future versions of Micro‐
+ soft's KMS server because multiple requests with different
+ clients-guids for the same kms-id-guid are impossible in a real
KMS szenario over the same TCP connection.
-c client-machine-guid
- Normally vlmcs generates a random client-machine-guid for each
- request. By using this option you can specify a fixed client-
- machine-guid This causes a Microsoft KMS not to increment its
- client count because it receives multiple requests for the same
- client. Thus do not use -c if you want to charge a real KMS
+ Normally vlmcs generates a random client-machine-guid for each
+ request. By using this option you can specify a fixed client-
+ machine-guid This causes a Microsoft KMS not to increment its
+ client count because it receives multiple requests for the same
+ client. Thus do not use -c if you want to charge a real KMS
server.
-o previous-client-machine-guid
If the client-machine-guid changes for some reason, the real KMS
- client stores a previous-client-machine-guid which is sent to
- the KMS server. This happens rarely and usually
- 00000000-0000-0000-0000-000000000000 is used. You can use -o to
+ client stores a previous-client-machine-guid which is sent to
+ the KMS server. This happens rarely and usually
+ 00000000-0000-0000-0000-000000000000 is used. You can use -o to
specify a different previous-client-machine-guid.
-G filename
- Grabs ePIDs and HWIDs from a KMS server and writes the informa‐
- tion to filename in format suitable to be used as a configura‐
+ Grabs ePIDs and HWIDs from a KMS server and writes the informa‐
+ tion to filename in format suitable to be used as a configura‐
tion file (aka ini file) for vlmcsd(8). This is especially use‐
- ful if you have access to a genuine KMS server and want to use
+ ful if you have access to a genuine KMS server and want to use
the same data with vlmcsd(8).
- If filename does not exist, it will be created. If you specify
- an existing filename, it will be updated to use the information
- received from the remote KMS server and a backup filename~ will
+ If filename does not exist, it will be created. If you specify
+ an existing filename, it will be updated to use the information
+ received from the remote KMS server and a backup filename~ will
be created.
-G cannot be used with -l, -4, -5, -6, -a, -s, -k, -r and -n
-w workstation-name
- Send requests with a specific workstation-name. This disables
- the random generator for the workstation name. Since it is a
+ Send requests with a specific workstation-name. This disables
+ the random generator for the workstation name. Since it is a
comment only, this option does not have much effect.
-r required-client-count
- Also known as the "N count policy". Tells the KMS server that
- successful activation requires required-client-count clients.
- The default is the required-client-count that the product would
- need if the request was a real activation. A Microsoft KMS
+ Also known as the "N count policy". Tells the KMS server that
+ successful activation requires required-client-count clients.
+ The default is the required-client-count that the product would
+ need if the request was a real activation. A Microsoft KMS
server counts clients up to the double amount what was specified
with -r. This option can be used to "overcharge" a Microsoft KMS
server.
@@ -197,57 +205,57 @@ OPTIONS
-t status
Reports a specific license status to the KMS server. status is a
- number that can be from 0 to 6. 0=unlicensed, 1=licensed, 2=OOB
- grace, 3=OOT grace, 4=Non-genuinue grace, 5=notification,
+ number that can be from 0 to 6. 0=unlicensed, 1=licensed, 2=OOB
+ grace, 3=OOT grace, 4=Non-genuinue grace, 5=notification,
6=extended grace. Refer to TechNet ⟨http://
technet.microsoft.com/en-us/library/ff686879.aspx#_Toc257201371⟩
- for more information. A Microsoft KMS server collects this
+ for more information. A Microsoft KMS server collects this
information for statistics only.
-g binding-expiration
- This tells the KMS server how long a client will stay in its
- current license status. This can be the remaining OOB time (the
- grace peroid that is granted between installation of a product
- and when activation is actuall required) or the remaining time
- when KMS activation must be renewed. binding-expiration is
+ This tells the KMS server how long a client will stay in its
+ current license status. This can be the remaining OOB time (the
+ grace peroid that is granted between installation of a product
+ and when activation is actuall required) or the remaining time
+ when KMS activation must be renewed. binding-expiration is
specified in minutes. A Microsoft KMS server apparantly does not
use this information.
-i protocol-version
- Force the use of Internet protocol protocol-version. Allowed
- values are 4 (IPv4) and 6 (IPv6). This option is useful only if
- you specfiy a hostname and not an ip-address on the command
+ Force the use of Internet protocol protocol-version. Allowed
+ values are 4 (IPv4) and 6 (IPv6). This option is useful only if
+ you specfiy a hostname and not an ip-address on the command
line.
- -p Do not set the RPC_PF_MULTIPLEX flag in the RPC bind request.
+ -p Do not set the RPC_PF_MULTIPLEX flag in the RPC bind request.
This can be used to test if the KMS server uses the same setting
- of this flag in the RPC bind respone. Some KMS emulators don't
+ of this flag in the RPC bind respone. Some KMS emulators don't
set this correctly.
-N0 and -N1
Disables (-N0) or enables (-N1) the NDR64 transfer syntax in the
- RPC protocol. Disable NDR64 only in case of problems. If NDR64
+ RPC protocol. Disable NDR64 only in case of problems. If NDR64
is not used, vlmcs cannot detect many RPC protocol errors in KMS
emulators. If you want to test whether a KMS emulator fully sup‐
- ports NDR64, you must use the -n option to send at least two
- requests. This is because Microsoft's client always sends the
- first request using NDR32 syntax and subsequent requests using
+ ports NDR64, you must use the -n option to send at least two
+ requests. This is because Microsoft's client always sends the
+ first request using NDR32 syntax and subsequent requests using
NDR64 syntax.
-B0 and -B1
- Disables (-B0) or enables (-B1) bind time feature negotiation
- (BTFN) in the RPC protocol. Disable BTFN only in case of prob‐
+ Disables (-B0) or enables (-B1) bind time feature negotiation
+ (BTFN) in the RPC protocol. Disable BTFN only in case of prob‐
lems. If BTFN is not used, vlmcs cannot detect many RPC protocol
errors in KMS emulators.
- Options that do not require an argument can be specified together with
- a single dash, e.g. vlmcs -6mvT. If you specify an option more than
+ Options that do not require an argument can be specified together with
+ a single dash, e.g. vlmcs -6mvT. If you specify an option more than
once, the last occurence will be in effect.
@@ -257,34 +265,34 @@ FILES
EXAMPLES
vlmcs kms.example.com
- Request activation for Windows Vista using v4 protocol from
- kms.example.com. Repeat activation requests until server is
+ Request activation for Windows Vista using v4 protocol from
+ kms.example.com. Repeat activation requests until server is
charged for all Windows products.
vlmcs -
- Request activation for Windows Vista using v4 protocol from a
+ Request activation for Windows Vista using v4 protocol from a
KMS server that is published via DNS for the current domain.
vlmcs .example.com
- Request activation for Windows Vista using v4 protocol from a
+ Request activation for Windows Vista using v4 protocol from a
KMS server that is published via DNS for domain example.com.
vlmcs -6 -l Office2013 -v -n 1
- Request exactly one activation for Office2013 using v6 protocol
+ Request exactly one activation for Office2013 using v6 protocol
from localhost. Display verbose results.
vlmcs kms.bigcompany.com -G /etc/vlmcsd.ini
- Get ePIDs and HWIDs from kms.bigcompany.com and create/update
+ Get ePIDs and HWIDs from kms.bigcompany.com and create/update
/etc/vlmcsd.ini accordingly.
BUGS
- Some platforms (e.g. Solaris) may have a man(7) system that does not
- handle URLs. URLs may be omitted in the documentation on those plat‐
+ Some platforms (e.g. Solaris) may have a man(7) system that does not
+ handle URLs. URLs may be omitted in the documentation on those plat‐
forms. Cygwin, Linux, FreeBSD and Mac OS X are known to work correctly.
@@ -293,7 +301,7 @@ AUTHOR
CREDITS
- Thanks to CODYQX4, crony12, deagles, DougQaid, eIcn, mikmik38, nos‐
+ Thanks to CODYQX4, crony12, deagles, DougQaid, eIcn, mikmik38, nos‐
ferati87, qad, Ratiborus, vityan666, ...
@@ -302,4 +310,4 @@ SEE ALSO
-Hotbird64 February 2015 VLMCS(1)
+Hotbird64 May 2016 VLMCS(1)
diff --git a/vlmcs.1.html b/vlmcs.1.html
index e17bc8a..5336450 100644
--- a/vlmcs.1.html
+++ b/vlmcs.1.html
@@ -1,5 +1,5 @@
-
+
@@ -55,7 +55,7 @@ can be one of the following:
hostname|ipaddress[:tcp-port]
-or to query a specific KMS server (example: vlmcs
+to query a specific KMS server (example: vlmcs
kms.example.com:1688).
.domain to automatically detect KMS servers via DNS
for domain (example: vlmcs .example.com). Please note
@@ -121,6 +121,23 @@ server in a home environment.
+ -V |
+ |
+
+
+
+ Displays extended version information. This includes the
+compiler used to build vlmcs, the intended platform and
+flags (compile time options) to build vlmcs. If you have the
+source code of vlmcsd, you can type make help (or
+gmake help on systems that do not use the GNU version
+of make(1) by default) to see the meaning of those
+flags. |
+
+ |
+
+
+
-x |
|
diff --git a/vlmcs.1.pdf b/vlmcs.1.pdf
index 75d637a..b3a9f43 100644
Binary files a/vlmcs.1.pdf and b/vlmcs.1.pdf differ
diff --git a/vlmcs.1.unix.txt b/vlmcs.1.unix.txt
index f6706d8..d6a6438 100644
--- a/vlmcs.1.unix.txt
+++ b/vlmcs.1.unix.txt
@@ -11,7 +11,7 @@ SYNOPSIS
target can be one of the following:
- hostname|ipaddress[:tcp-port] or to query a specific KMS server
+ hostname|ipaddress[:tcp-port] to query a specific KMS server
(example: vlmcs kms.example.com:1688).
.domain to automatically detect KMS servers via DNS for domain
(example: vlmcs .example.com). Please note the dot before
@@ -52,6 +52,14 @@ OPTIONS
Show help.
+ -V Displays extended version information. This includes the com‐
+ piler used to build vlmcs, the intended platform and flags (com‐
+ pile time options) to build vlmcs. If you have the source code
+ of vlmcsd, you can type make help (or gmake help on systems that
+ do not use the GNU version of make(1) by default) to see the
+ meaning of those flags.
+
+
-x Show valid applications that can be used with -l.
@@ -59,44 +67,44 @@ OPTIONS
-v Be verbose. Instead of just displaying the returned ePID and the
- HwId (protocol v6 only) vlmcsd shows all details of the query
+ HwId (protocol v6 only) vlmcsd shows all details of the query
and the response.
-l application
- Request activation for a specific application. Valid applica‐
- tions can be displayed by using -x. The default application is
- Windows Vista Business. The list of available applications is
+ Request activation for a specific application. Valid applica‐
+ tions can be displayed by using -x. The default application is
+ Windows Vista Business. The list of available applications is
not complete. You may supply GUIDs with -a, -k and -s to specify
- applications that are not listed with -x. The -l option is used
+ applications that are not listed with -x. The -l option is used
as a shortcut for the most common applications.
-4, -5 and -6
- Force version 4, 5 or 6 of the KMS protocol. The default is to
+ Force version 4, 5 or 6 of the KMS protocol. The default is to
select a suitable version according to the application selected.
Plese note that some products (e.g. Office 2013) may use differ‐
ent protocols with different versions of Windows.
- -m Let the client pretend to be a virtual machine. Early versions
- of Microsoft's KMS server did not increase the client count if
- the request came from a virtual machine. Newer versions ignore
+ -m Let the client pretend to be a virtual machine. Early versions
+ of Microsoft's KMS server did not increase the client count if
+ the request came from a virtual machine. Newer versions ignore
this flag.
-d Use NetBIOS names instead of DNS names. By default vlmcsd gener‐
- ates some random DNS names for each request. If you prefer Net‐
- BIOS names, you may use -d. A real Microsoft activation client
- uses DNS names or NetBIOS depending on the client name configu‐
+ ates some random DNS names for each request. If you prefer Net‐
+ BIOS names, you may use -d. A real Microsoft activation client
+ uses DNS names or NetBIOS depending on the client name configu‐
ration. KMS servers treat the workstation name as a comment that
- affects logging only. Clients will be identified by a GUID that
- can be specified using -c. -d has no effect if you also specify
+ affects logging only. Clients will be identified by a GUID that
+ can be specified using -c. -d has no effect if you also specify
-w.
-a application-guid
- Send requests with a specific application-guid. There are cur‐
+ Send requests with a specific application-guid. There are cur‐
rently only three known valid application-guids:
@@ -105,91 +113,91 @@ OPTIONS
0ff1ce15-a989-479d-af46-f275c6370663 (Office 2013)
- A Microsoft KMS server uses these GUIDs to have seperate coun‐
- ters for the already activated clients. A client that does not
- contact the KMS server within 30 days will be deleted from the
+ A Microsoft KMS server uses these GUIDs to have seperate coun‐
+ ters for the already activated clients. A client that does not
+ contact the KMS server within 30 days will be deleted from the
database. Emulated KMS servers are always fully charged.
-k kms-guid
- Send requests with a specific kms-guid. A Microsoft KMS server
- uses these GUIDs as a product id to decide whether to grant
- activation or not. A list of current kms-guids can be found in
- kms.c (table KmsIdList). Emulated KMS servers grant activation
+ Send requests with a specific kms-guid. A Microsoft KMS server
+ uses these GUIDs as a product id to decide whether to grant
+ activation or not. A list of current kms-guids can be found in
+ kms.c (table KmsIdList). Emulated KMS servers grant activation
unconditionally and do not check the kms-guid.
-s activation-guid
- The activation-guid defines the actual product, e.g. "Windows
- 8.1 Professional WMC KMSCLIENT edition". A activation-guid maps
- 1:1 to a product key. However, neither a Microsoft KMS server
+ The activation-guid defines the actual product, e.g. "Windows
+ 8.1 Professional WMC KMSCLIENT edition". A activation-guid maps
+ 1:1 to a product key. However, neither a Microsoft KMS server
nor emulated servers check this id. The activation-guid is use‐
- ful in logging to get a specific product description like "Win‐
- dows 8.1 Professional WMC". A list of current activation-guids
+ ful in logging to get a specific product description like "Win‐
+ dows 8.1 Professional WMC". A list of current activation-guids
can be found in kms.c (table ExtendedProductList).
-n requests
- Send requests requests to the server. The default is to send at
+ Send requests requests to the server. The default is to send at
least one request and enough subsequent requests that the server
- is fully charged afterwards for the application-guid you
+ is fully charged afterwards for the application-guid you
selected (explicitly with -a or implicitly by using -l).
- -T Causes to use a new TCP connection for each request if multiple
- requests are sent with vlmcsd. This is useful when you want to
- test an emulated KMS server whether it suffers from memory
- leaks. To test for memory leaks use -n with a large number of
- requests (> 100000) and then test twice (with and without -T).
- This option may become neccessary for future versions of Micro‐
- soft's KMS server because multiple requests with different
- clients-guids for the same kms-id-guid are impossible in a real
+ -T Causes to use a new TCP connection for each request if multiple
+ requests are sent with vlmcsd. This is useful when you want to
+ test an emulated KMS server whether it suffers from memory
+ leaks. To test for memory leaks use -n with a large number of
+ requests (> 100000) and then test twice (with and without -T).
+ This option may become neccessary for future versions of Micro‐
+ soft's KMS server because multiple requests with different
+ clients-guids for the same kms-id-guid are impossible in a real
KMS szenario over the same TCP connection.
-c client-machine-guid
- Normally vlmcs generates a random client-machine-guid for each
- request. By using this option you can specify a fixed client-
- machine-guid This causes a Microsoft KMS not to increment its
- client count because it receives multiple requests for the same
- client. Thus do not use -c if you want to charge a real KMS
+ Normally vlmcs generates a random client-machine-guid for each
+ request. By using this option you can specify a fixed client-
+ machine-guid This causes a Microsoft KMS not to increment its
+ client count because it receives multiple requests for the same
+ client. Thus do not use -c if you want to charge a real KMS
server.
-o previous-client-machine-guid
If the client-machine-guid changes for some reason, the real KMS
- client stores a previous-client-machine-guid which is sent to
- the KMS server. This happens rarely and usually
- 00000000-0000-0000-0000-000000000000 is used. You can use -o to
+ client stores a previous-client-machine-guid which is sent to
+ the KMS server. This happens rarely and usually
+ 00000000-0000-0000-0000-000000000000 is used. You can use -o to
specify a different previous-client-machine-guid.
-G filename
- Grabs ePIDs and HWIDs from a KMS server and writes the informa‐
- tion to filename in format suitable to be used as a configura‐
+ Grabs ePIDs and HWIDs from a KMS server and writes the informa‐
+ tion to filename in format suitable to be used as a configura‐
tion file (aka ini file) for vlmcsd(8). This is especially use‐
- ful if you have access to a genuine KMS server and want to use
+ ful if you have access to a genuine KMS server and want to use
the same data with vlmcsd(8).
- If filename does not exist, it will be created. If you specify
- an existing filename, it will be updated to use the information
- received from the remote KMS server and a backup filename~ will
+ If filename does not exist, it will be created. If you specify
+ an existing filename, it will be updated to use the information
+ received from the remote KMS server and a backup filename~ will
be created.
-G cannot be used with -l, -4, -5, -6, -a, -s, -k, -r and -n
-w workstation-name
- Send requests with a specific workstation-name. This disables
- the random generator for the workstation name. Since it is a
+ Send requests with a specific workstation-name. This disables
+ the random generator for the workstation name. Since it is a
comment only, this option does not have much effect.
-r required-client-count
- Also known as the "N count policy". Tells the KMS server that
- successful activation requires required-client-count clients.
- The default is the required-client-count that the product would
- need if the request was a real activation. A Microsoft KMS
+ Also known as the "N count policy". Tells the KMS server that
+ successful activation requires required-client-count clients.
+ The default is the required-client-count that the product would
+ need if the request was a real activation. A Microsoft KMS
server counts clients up to the double amount what was specified
with -r. This option can be used to "overcharge" a Microsoft KMS
server.
@@ -197,57 +205,57 @@ OPTIONS
-t status
Reports a specific license status to the KMS server. status is a
- number that can be from 0 to 6. 0=unlicensed, 1=licensed, 2=OOB
- grace, 3=OOT grace, 4=Non-genuinue grace, 5=notification,
+ number that can be from 0 to 6. 0=unlicensed, 1=licensed, 2=OOB
+ grace, 3=OOT grace, 4=Non-genuinue grace, 5=notification,
6=extended grace. Refer to TechNet ⟨http://
technet.microsoft.com/en-us/library/ff686879.aspx#_Toc257201371⟩
- for more information. A Microsoft KMS server collects this
+ for more information. A Microsoft KMS server collects this
information for statistics only.
-g binding-expiration
- This tells the KMS server how long a client will stay in its
- current license status. This can be the remaining OOB time (the
- grace peroid that is granted between installation of a product
- and when activation is actuall required) or the remaining time
- when KMS activation must be renewed. binding-expiration is
+ This tells the KMS server how long a client will stay in its
+ current license status. This can be the remaining OOB time (the
+ grace peroid that is granted between installation of a product
+ and when activation is actuall required) or the remaining time
+ when KMS activation must be renewed. binding-expiration is
specified in minutes. A Microsoft KMS server apparantly does not
use this information.
-i protocol-version
- Force the use of Internet protocol protocol-version. Allowed
- values are 4 (IPv4) and 6 (IPv6). This option is useful only if
- you specfiy a hostname and not an ip-address on the command
+ Force the use of Internet protocol protocol-version. Allowed
+ values are 4 (IPv4) and 6 (IPv6). This option is useful only if
+ you specfiy a hostname and not an ip-address on the command
line.
- -p Do not set the RPC_PF_MULTIPLEX flag in the RPC bind request.
+ -p Do not set the RPC_PF_MULTIPLEX flag in the RPC bind request.
This can be used to test if the KMS server uses the same setting
- of this flag in the RPC bind respone. Some KMS emulators don't
+ of this flag in the RPC bind respone. Some KMS emulators don't
set this correctly.
-N0 and -N1
Disables (-N0) or enables (-N1) the NDR64 transfer syntax in the
- RPC protocol. Disable NDR64 only in case of problems. If NDR64
+ RPC protocol. Disable NDR64 only in case of problems. If NDR64
is not used, vlmcs cannot detect many RPC protocol errors in KMS
emulators. If you want to test whether a KMS emulator fully sup‐
- ports NDR64, you must use the -n option to send at least two
- requests. This is because Microsoft's client always sends the
- first request using NDR32 syntax and subsequent requests using
+ ports NDR64, you must use the -n option to send at least two
+ requests. This is because Microsoft's client always sends the
+ first request using NDR32 syntax and subsequent requests using
NDR64 syntax.
-B0 and -B1
- Disables (-B0) or enables (-B1) bind time feature negotiation
- (BTFN) in the RPC protocol. Disable BTFN only in case of prob‐
+ Disables (-B0) or enables (-B1) bind time feature negotiation
+ (BTFN) in the RPC protocol. Disable BTFN only in case of prob‐
lems. If BTFN is not used, vlmcs cannot detect many RPC protocol
errors in KMS emulators.
- Options that do not require an argument can be specified together with
- a single dash, e.g. vlmcs -6mvT. If you specify an option more than
+ Options that do not require an argument can be specified together with
+ a single dash, e.g. vlmcs -6mvT. If you specify an option more than
once, the last occurence will be in effect.
@@ -257,34 +265,34 @@ FILES
EXAMPLES
vlmcs kms.example.com
- Request activation for Windows Vista using v4 protocol from
- kms.example.com. Repeat activation requests until server is
+ Request activation for Windows Vista using v4 protocol from
+ kms.example.com. Repeat activation requests until server is
charged for all Windows products.
vlmcs -
- Request activation for Windows Vista using v4 protocol from a
+ Request activation for Windows Vista using v4 protocol from a
KMS server that is published via DNS for the current domain.
vlmcs .example.com
- Request activation for Windows Vista using v4 protocol from a
+ Request activation for Windows Vista using v4 protocol from a
KMS server that is published via DNS for domain example.com.
vlmcs -6 -l Office2013 -v -n 1
- Request exactly one activation for Office2013 using v6 protocol
+ Request exactly one activation for Office2013 using v6 protocol
from localhost. Display verbose results.
vlmcs kms.bigcompany.com -G /etc/vlmcsd.ini
- Get ePIDs and HWIDs from kms.bigcompany.com and create/update
+ Get ePIDs and HWIDs from kms.bigcompany.com and create/update
/etc/vlmcsd.ini accordingly.
BUGS
- Some platforms (e.g. Solaris) may have a man(7) system that does not
- handle URLs. URLs may be omitted in the documentation on those plat‐
+ Some platforms (e.g. Solaris) may have a man(7) system that does not
+ handle URLs. URLs may be omitted in the documentation on those plat‐
forms. Cygwin, Linux, FreeBSD and Mac OS X are known to work correctly.
@@ -293,7 +301,7 @@ AUTHOR
CREDITS
- Thanks to CODYQX4, crony12, deagles, DougQaid, eIcn, mikmik38, nos‐
+ Thanks to CODYQX4, crony12, deagles, DougQaid, eIcn, mikmik38, nos‐
ferati87, qad, Ratiborus, vityan666, ...
@@ -302,4 +310,4 @@ SEE ALSO
-Hotbird64 February 2015 VLMCS(1)
+Hotbird64 May 2016 VLMCS(1)
diff --git a/vlmcs.c b/vlmcs.c
index db6a60f..ddb77bd 100644
--- a/vlmcs.c
+++ b/vlmcs.c
@@ -46,7 +46,10 @@ static void CreateRequestBase(REQUEST *Request);
// KMS Parameters
+#ifndef NO_VERBOSE_LOG
static int_fast8_t verbose = FALSE;
+#endif
+
static int_fast8_t VMInfo = FALSE;
static int_fast8_t dnsnames = TRUE;
static int FixedRequests = 0;
@@ -160,7 +163,9 @@ __noreturn static void clientUsage(const char* const programName)
"Options:\n\n"
+# ifndef NO_VERBOSE_LOG
" -v Be verbose\n"
+# endif
" -l \n"
" -4 Force V4 protocol\n"
" -5 Force V5 protocol\n"
@@ -170,7 +175,8 @@ __noreturn static void clientUsage(const char* const programName)
# endif // USE_MSRPC
" -e Show some valid examples\n"
" -x Show valid Apps\n"
- " -d no DNS names, use Netbios names (no effect if -w is used)\n\n"
+ " -d no DNS names, use Netbios names (no effect if -w is used)\n"
+ " -V show version information and exit\n\n"
"Advanced options:\n\n"
@@ -420,7 +426,7 @@ static BOOL findLicensePackByName(const char* const name, LicensePack* const lp)
#endif // Both Lists are available
}
-static const char* const client_optstring = "+N:B:i:l:a:s:k:c:w:r:n:t:g:G:o:pPTv456mexd";
+static const char* const client_optstring = "+N:B:i:l:a:s:k:c:w:r:n:t:g:G:o:pPTv456mexdV";
//First pass. We handle only "-l". Since -a -k -s -4 -5 and -6 are exceptions to -l, we process -l first
@@ -584,11 +590,15 @@ static void parseCommandLinePass2(const char *const programName, const int argc,
dnsnames = FALSE;
break;
+# ifndef NO_VERBOSE_LOG
+
case 'v': // Be verbose
verbose = TRUE;
break;
+# endif // NO_VERBOSE_LOG
+
case 'm': // Pretend to be a virtual machine
VMInfo = TRUE;
@@ -623,6 +633,21 @@ static void parseCommandLinePass2(const char *const programName, const int argc,
incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
break;
+# ifndef NO_VERSION_INFORMATION
+
+ case 'V':
+# if defined(__s390__) && !defined(__zarch__) && !defined(__s390x__)
+ printf("vlmcs %s %i-bit\n", Version, sizeof(void*) == 4 ? 31 : (int)sizeof(void*) << 3);
+# else
+ printf("vlmcs %s %i-bit\n", Version, (int)sizeof(void*) << 3);
+# endif // defined(__s390__) && !defined(__zarch__) && !defined(__s390x__)
+ printPlatform();
+ printCommonFlags();
+ printClientFlags();
+ exit(0);
+
+# endif // NO_VERSION_INFORMATION
+
default:
clientUsage(programName);
}
@@ -651,8 +676,10 @@ static void checkRpcLevel(const REQUEST* request, RESPONSE* response)
if (UseRpcBTFN && UseRpcNDR64 && RpcFlags.HasNDR64 && !RpcFlags.HasBTFN)
errorout("\nWARNING: Server's RPC protocol has NDR64 but no BTFN.\n");
+# ifndef NO_BASIC_PRODUCT_LIST
if (!IsEqualGuidLEHE(&request->KMSID, &ProductList[15].guid) && UseRpcBTFN && !RpcFlags.HasBTFN)
errorout("\nWARNING: A server with pre-Vista RPC activated a product other than Office 2010.\n");
+# endif // NO_BASIC_PRODUCT_LIST
}
#endif // USE_MSRPC
@@ -690,7 +717,9 @@ static void displayResponse(const RESPONSE_RESULT result, const REQUEST* request
}
// Read KMSPID from Response
+# ifndef NO_VERBOSE_LOG
if (!verbose)
+# endif // NO_VERBOSE_LOG
{
printf(" -> %s", ePID);
@@ -705,6 +734,7 @@ static void displayResponse(const RESPONSE_RESULT result, const REQUEST* request
printf("\n");
}
+# ifndef NO_VERBOSE_LOG
else
{
printf(
@@ -715,6 +745,7 @@ static void displayResponse(const RESPONSE_RESULT result, const REQUEST* request
logResponseVerbose(ePID, hwid, response, &printf);
printf("\n");
}
+# endif // NO_VERBOSE_LOG
}
@@ -760,6 +791,7 @@ static void connectRpc(RpcCtx *s)
if (!NoSrvRecordPriority) sortSrvRecords(serverlist, numServers);
+# ifndef NO_VERBOSE_LOG
if (verbose /*&& !ServerListAlreadyPrinted*/)
{
for (i = 0; i < numServers; i++)
@@ -775,6 +807,7 @@ static void connectRpc(RpcCtx *s)
printf("\n");
//ServerListAlreadyPrinted = TRUE;
}
+# endif // NO_VERBOSE_LOG
}
else // Just use the server supplied on the command line
{
@@ -794,16 +827,21 @@ static void connectRpc(RpcCtx *s)
if (*s == INVALID_RPCCTX) continue;
- if (verbose)
- printf("\nPerforming RPC bind ...\n");
+# ifndef NO_VERBOSE_LOG
+ if (verbose) printf("\nPerforming RPC bind ...\n");
if (rpcBindClient(*s, verbose))
+# else
+ if (rpcBindClient(*s, FALSE))
+# endif
{
errorout("Warning: Could not bind RPC\n");
continue;
}
+# ifndef NO_VERBOSE_LOG
if (verbose) printf("... successful\n");
+# endif
return;
}
@@ -1298,13 +1336,14 @@ static void CreateRequestBase(REQUEST *Request)
Request->WorkstationName[size] = 0;
}
- //Show Details
+# ifndef NO_VERBOSE_LOG
if (verbose)
{
printf("\nRequest Parameters\n==================\n\n");
logRequestVerbose(Request, &printf);
printf("\n");
}
+# endif // NO_VERBOSE_LOG
}
diff --git a/vlmcs_all.c b/vlmcs_all.c
deleted file mode 100644
index 9bae523..0000000
--- a/vlmcs_all.c
+++ /dev/null
@@ -1,6525 +0,0 @@
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include "vlmcs.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#ifndef _WIN32
-#include
-#include
-#else // _WIN32
-#endif // _WIN32
-#include "endian.h"
-#include "shared_globals.h"
-#include "output.h"
-#ifndef USE_MSRPC
-#include "network.h"
-#include "rpc.h"
-#else // USE_MSRPC
-#include "msrpc-client.h"
-#endif // USE_MSRPC
-#include "kms.h"
-#include "helpers.h"
-#include "dns_srv.h"
-
-
-#define VLMCS_OPTION_GRAB_INI 1
-#define VLMCS_OPTION_NO_GRAB_INI 2
-
-#define kmsVersionMinor 0 // Currently constant. May change in future KMS versions
-
-// Function Prototypes
-static void CreateRequestBase(REQUEST *Request);
-
-
-// KMS Parameters
-static int_fast8_t verbose = FALSE;
-static int_fast8_t VMInfo = FALSE;
-static int_fast8_t dnsnames = TRUE;
-static int FixedRequests = 0;
-static BYTE LicenseStatus = 0x02;
-static const char *CMID = NULL;
-static const char *CMID_prev = NULL;
-static const char *WorkstationName = NULL;
-static int BindingExpiration = 43200; //30 days
-static const char *RemoteAddr;
-static int_fast8_t ReconnectForEachRequest = FALSE;
-static int AddressFamily = AF_UNSPEC;
-static int_fast8_t incompatibleOptions = 0;
-static const char* fn_ini_client = NULL;
-
-#ifndef NO_DNS
-static int_fast8_t NoSrvRecordPriority = FALSE;
-#endif // NO_DNS
-
-
-// Structure for handling "License Packs" (e.g. Office2013v5 or WindowsVista)
-typedef struct
-{
- const char *names; //This is a list of strings. Terminate with additional Zero!!!
- int N_Policy;
- int kmsVersionMajor;
- const GUID *AppID;
- GUID ActID;
- GUID KMSID;
-} LicensePack;
-
-
-typedef char iniFileEpidLines[3][256];
-
-// Well known "license packs"
-static const LicensePack LicensePackList[] =
-{
- // List of names min lics version appID skuId KMSCountedID
- /* 000 */ { "Vista\000W6\000"
- "WindowsVista\000"
- "Windows\000", 25, 4, PWINGUID, { 0x4f3d1606, 0x3fea, 0x4c01, { 0xbe, 0x3c, 0x8d, 0x67, 0x1c, 0x40, 0x1e, 0x3b, } }, { 0x212a64dc, 0x43b1, 0x4d3d, { 0xa3, 0x0c, 0x2f, 0xc6, 0x9d, 0x20, 0x95, 0xc6 } } },
- /* 001 */ { "W7\000Windows7\000", 25, 4, PWINGUID, { 0xb92e9980, 0xb9d5, 0x4821, { 0x9c, 0x94, 0x14, 0x0f, 0x63, 0x2f, 0x63, 0x12, } }, { 0x7fde5219, 0xfbfa, 0x484a, { 0x82, 0xc9, 0x34, 0xd1, 0xad, 0x53, 0xe8, 0x56 } } },
- /* 002 */ { "W8\000Windows8\000", 25, 5, PWINGUID, { 0xa98bcd6d, 0x5343, 0x4603, { 0x8a, 0xfe, 0x59, 0x08, 0xe4, 0x61, 0x11, 0x12, } }, { 0x3c40b358, 0x5948, 0x45af, { 0x92, 0x3b, 0x53, 0xd2, 0x1f, 0xcc, 0x7e, 0x79 } } },
- /* 003 */ { "W8C\000Windows8C\000", 25, 5, PWINGUID, { 0xc04ed6bf, 0x55c8, 0x4b47, { 0x9f, 0x8e, 0x5a, 0x1f, 0x31, 0xce, 0xee, 0x60, } }, { 0xbbb97b3b, 0x8ca4, 0x4a28, { 0x97, 0x17, 0x89, 0xfa, 0xbd, 0x42, 0xc4, 0xac } } },
- /* 004 */ { "W81\000Windows81\000", 25, 6, PWINGUID, { 0xc06b6981, 0xd7fd, 0x4a35, { 0xb7, 0xb4, 0x05, 0x47, 0x42, 0xb7, 0xaf, 0x67, } }, { 0xcb8fc780, 0x2c05, 0x495a, { 0x97, 0x10, 0x85, 0xaf, 0xff, 0xc9, 0x04, 0xd7 } } },
- /* 005 */ { "W81C\000Windows81C\000", 25, 6, PWINGUID, { 0xfe1c3238, 0x432a, 0x43a1, { 0x8e, 0x25, 0x97, 0xe7, 0xd1, 0xef, 0x10, 0xf3, } }, { 0x6d646890, 0x3606, 0x461a, { 0x86, 0xab, 0x59, 0x8b, 0xb8, 0x4a, 0xce, 0x82 } } },
- /* 006 */ { "W10\000Windows10\000", 25, 6, PWINGUID, { 0x73111121, 0x5638, 0x40f6, { 0xbc, 0x11, 0xf1, 0xd7, 0xb0, 0xd6, 0x43, 0x00, } }, { 0x58e2134f, 0x8e11, 0x4d17, { 0x9c, 0xb2, 0x91, 0x06, 0x9c, 0x15, 0x11, 0x48 } } },
- /* 007 */ { "W10C\000Windows10C\000", 25, 6, PWINGUID, { 0x58e97c99, 0xf377, 0x4ef1, { 0x81, 0xd5, 0x4a, 0xd5, 0x52, 0x2b, 0x5f, 0xd8, } }, { 0xe1c51358, 0xfe3e, 0x4203, { 0xa4, 0xa2, 0x3b, 0x6b, 0x20, 0xc9, 0x73, 0x4e } } },
- /* 008 */ { "2008" "\0" "2008A\000", 5, 4, PWINGUID, { 0xddfa9f7c, 0xf09e, 0x40b9, { 0x8c, 0x1a, 0xbe, 0x87, 0x7a, 0x9a, 0x7f, 0x4b, } }, { 0x33e156e4, 0xb76f, 0x4a52, { 0x9f, 0x91, 0xf6, 0x41, 0xdd, 0x95, 0xac, 0x48 } } },
- /* 009 */ { "2008B\000", 5, 4, PWINGUID, { 0xc1af4d90, 0xd1bc, 0x44ca, { 0x85, 0xd4, 0x00, 0x3b, 0xa3, 0x3d, 0xb3, 0xb9, } }, { 0x8fe53387, 0x3087, 0x4447, { 0x89, 0x85, 0xf7, 0x51, 0x32, 0x21, 0x5a, 0xc9 } } },
- /* 010 */ { "2008C\000", 5, 4, PWINGUID, { 0x68b6e220, 0xcf09, 0x466b, { 0x92, 0xd3, 0x45, 0xcd, 0x96, 0x4b, 0x95, 0x09, } }, { 0x8a21fdf3, 0xcbc5, 0x44eb, { 0x83, 0xf3, 0xfe, 0x28, 0x4e, 0x66, 0x80, 0xa7 } } },
- /* 011 */ { "2008R2" "\0" "2008R2A\000", 5, 4, PWINGUID, { 0xa78b8bd9, 0x8017, 0x4df5, { 0xb8, 0x6a, 0x09, 0xf7, 0x56, 0xaf, 0xfa, 0x7c, } }, { 0x0fc6ccaf, 0xff0e, 0x4fae, { 0x9d, 0x08, 0x43, 0x70, 0x78, 0x5b, 0xf7, 0xed } } },
- /* 012 */ { "2008R2B\000", 5, 4, PWINGUID, { 0x620e2b3d, 0x09e7, 0x42fd, { 0x80, 0x2a, 0x17, 0xa1, 0x36, 0x52, 0xfe, 0x7a, } }, { 0xca87f5b6, 0xcd46, 0x40c0, { 0xb0, 0x6d, 0x8e, 0xcd, 0x57, 0xa4, 0x37, 0x3f } } },
- /* 013 */ { "2008R2C\000", 5, 4, PWINGUID, { 0x7482e61b, 0xc589, 0x4b7f, { 0x8e, 0xcc, 0x46, 0xd4, 0x55, 0xac, 0x3b, 0x87, } }, { 0xb2ca2689, 0xa9a8, 0x42d7, { 0x93, 0x8d, 0xcf, 0x8e, 0x9f, 0x20, 0x19, 0x58 } } },
- /* 014 */ { "2012\000", 5, 5, PWINGUID, { 0xf0f5ec41, 0x0d55, 0x4732, { 0xaf, 0x02, 0x44, 0x0a, 0x44, 0xa3, 0xcf, 0x0f, } }, { 0x8665cb71, 0x468c, 0x4aa3, { 0xa3, 0x37, 0xcb, 0x9b, 0xc9, 0xd5, 0xea, 0xac } } },
- /* 015 */ { "2012R2\000" "12R2\000", 5, 6, PWINGUID, { 0x00091344, 0x1ea4, 0x4f37, { 0xb7, 0x89, 0x01, 0x75, 0x0b, 0xa6, 0x98, 0x8c, } }, { 0x8456EFD3, 0x0C04, 0x4089, { 0x87, 0x40, 0x5b, 0x72, 0x38, 0x53, 0x5a, 0x65 } } },
- /* 016 */ { "Office2010\000O14\000", 5, 4, POFFICE2010GUID, { 0x6f327760, 0x8c5c, 0x417c, { 0x9b, 0x61, 0x83, 0x6a, 0x98, 0x28, 0x7e, 0x0c, } }, { 0xe85af946, 0x2e25, 0x47b7, { 0x83, 0xe1, 0xbe, 0xbc, 0xeb, 0xea, 0xc6, 0x11 } } },
- /* 017 */ { "Office2013\000O15\000", 5, 6, POFFICE2013GUID, { 0xb322da9c, 0xa2e2, 0x4058, { 0x9e, 0x4e, 0xf5, 0x9a, 0x69, 0x70, 0xbd, 0x69, } }, { 0xe6a6f1bf, 0x9d40, 0x40c3, { 0xaa, 0x9f, 0xc7, 0x7b, 0xa2, 0x15, 0x78, 0xc0 } } },
- /* 018 */ { "Office2013V5\000", 5, 5, POFFICE2013GUID, { 0xb322da9c, 0xa2e2, 0x4058, { 0x9e, 0x4e, 0xf5, 0x9a, 0x69, 0x70, 0xbd, 0x69, } }, { 0xe6a6f1bf, 0x9d40, 0x40c3, { 0xaa, 0x9f, 0xc7, 0x7b, 0xa2, 0x15, 0x78, 0xc0 } } },
- /* 019 */ { "Office2016\000" "O16\000", 5, 6, POFFICE2013GUID, { 0xd450596f, 0x894d, 0x49e0, { 0x96, 0x6a, 0xfd, 0x39, 0xed, 0x4c, 0x4c, 0x64, } }, { 0x85b5f61b, 0x320b, 0x4be3, { 0x81, 0x4a, 0xb7, 0x6b, 0x2b, 0xfa, 0xfc, 0x82 } } },
- /* 020 */ { NULL, 0, 0, NULL, { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } }, { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } }
-};
-
-
-typedef struct
-{
- const char* first[16];
- const char* second[16];
- const char* tld[22];
-} DnsNames;
-
-
-// Some names for the DNS name random generator
-static DnsNames ClientDnsNames =
-{
- { "www", "ftp", "kms", "hack-me", "smtp", "ns1", "mx1", "ns1", "pop3", "imap", "mail", "dns", "headquarter", "we-love", "_vlmcs._tcp", "ceo-laptop" },
- { ".microsoft", ".apple", ".amazon", ".samsung", ".adobe", ".google", ".yahoo", ".facebook", ".ubuntu", ".oracle", ".borland", ".htc", ".acer", ".windows", ".linux", ".sony" },
- { ".com", ".net", ".org", ".cn", ".co.uk", ".de", ".com.tw", ".us", ".fr", ".it", ".me", ".info", ".biz", ".co.jp", ".ua", ".at", ".es", ".pro", ".by", ".ru", ".pl", ".kr" }
-};
-
-
-// This is the one, we are actually using. We use Vista, if user selects nothing
-LicensePack ActiveLicensePack;
-
-
-// Request Count Control Variables
-static int RequestsToGo = 1;
-static BOOL firstRequestSent = FALSE;
-
-
-static void string2UuidOrExit(const char *const restrict input, GUID *const restrict guid)
-{
- if (strlen(input) != GUID_STRING_LENGTH || !string2Uuid(input, guid))
- {
- errorout("Fatal: Command line contains an invalid GUID.\n");
- exit(!0);
- }
-}
-
-
-#ifndef NO_HELP
-
-__noreturn static void clientUsage(const char* const programName)
-{
- errorout(
- "vlmcs %s \n\n"
-# ifndef NO_DNS
- "Usage: %s [options] [ [:] | . | - ] [options]\n\n"
-# else // DNS
- "Usage: %s [options] [[:]] [options]\n\n"
-# endif // DNS
-
- "Options:\n\n"
-
- " -v Be verbose\n"
- " -l \n"
- " -4 Force V4 protocol\n"
- " -5 Force V5 protocol\n"
- " -6 Force V6 protocol\n"
-# ifndef USE_MSRPC
- " -i Use IP protocol (4 or 6)\n"
-# endif // USE_MSRPC
- " -e Show some valid examples\n"
- " -x Show valid Apps\n"
- " -d no DNS names, use Netbios names (no effect if -w is used)\n\n"
-
- "Advanced options:\n\n"
-
- " -a Use custom Application GUID\n"
- " -s Use custom Activation Configuration GUID\n"
- " -k Use custom KMS GUID\n"
- " -c Use custom Client GUID. Default: Use random\n"
- " -o Use custom Prevoius Client GUID. Default: ZeroGUID\n"
- " -w Use custom workstation name. Default: Use random\n"
- " -r Fake required clients\n"
- " -n Fixed # of requests (Default: Enough to charge)\n"
- " -m Pretend to be a virtual machine\n"
- " -G Get ePID/HwId data and write to . Can't be used with -l, -4, -5, -6, -a, -s, -k, -r and -n\n"
-# ifndef USE_MSRPC
- " -T Use a new TCP connection for each request.\n"
- " -N <0|1> disable or enable NDR64. Default: 1\n"
- " -B <0|1> disable or enable RPC bind time feature negotiation. Default: 1\n"
-# endif // USE_MSRPC
- " -t Use specfic license status (0 <= T <= 6)\n"
- " -g Use a specfic binding expiration time in minutes. Default 43200\n"
-# ifndef NO_DNS
- " -P Ignore priority and weight in DNS SRV records\n"
-# endif // NO_DNS
-# ifndef USE_MSRPC
- " -p Don't use multiplexed RPC bind\n"
-# endif // USE_MSRPC
- "\n"
-
- ":\t\tTCP port name of the KMS to use. Default 1688.\n"
- ":\t\thost name of the KMS to use. Default 127.0.0.1\n"
-# ifndef NO_DNS
- ".:\tfind KMS server in via DNS\n"
-# endif // NO_DNS
- ":\t\t(Type %s -x to see a list of valid apps)\n\n",
- Version, programName, programName
- );
-
- exit(!0);
-}
-
-__pure static int getLineWidth(void)
-{
- #ifdef TERMINAL_FIXED_WIDTH // For Toolchains that to not have winsize
- return TERMINAL_FIXED_WIDTH;
- #else // Can determine width of terminal
- #ifndef _WIN32
-
- struct winsize w;
-
- if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w))
- {
- return 80; // Return this if stdout is not a tty
- }
-
- return w.ws_col;
-
- #else // _WIN32
-
- CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
- HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
-
- if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
- {
- return 80; // Return this if stdout is not a Console
- }
-
- return csbiInfo.srWindow.Right - csbiInfo.srWindow.Left;
-
- #endif // WIN32
-
- #endif // Can determine width of terminal
-
-}
-
-__noreturn static void showProducts(PRINTFUNC p)
-{
- int cols = getLineWidth();
- int itemsPerLine;
- uint8_t i;
-
- p(
- "The following "
- #if !defined(NO_EXTENDED_PRODUCT_LIST) && !defined(NO_BASIC_PRODUCT_LIST)
- "aliases "
- #else
- "names "
- #endif
- "can be used with -l:\n\n"
- );
-
- const LicensePack* lp;
-
- itemsPerLine = cols / 20;
- if (!itemsPerLine) itemsPerLine = 1;
-
- for (i = 1, lp = LicensePackList; lp->names; lp++)
- {
- const char* name;
-
- for (name = lp->names; *name; name += strlen(name) + 1, i++)
- {
- p("%-20s", name);
-
- if (!(i % itemsPerLine)) p("\n");
- }
- }
-
- p("\n\n");
-
- #if !defined(NO_EXTENDED_PRODUCT_LIST) && !defined(NO_BASIC_PRODUCT_LIST)
-
- const KmsIdList* currentProduct;
- uint_fast8_t longestString = 0;
- uint8_t k, items = getExtendedProductListSize();
-
- p("You may also use these product names or numbers:\n\n");
-
- for (currentProduct = ExtendedProductList; currentProduct->name; currentProduct++)
- {
- uint_fast8_t len = strlen(currentProduct->name);
-
- if (len > longestString)
- longestString = len;
- }
-
- itemsPerLine = cols / (longestString + 10);
- if (!itemsPerLine) itemsPerLine = 1;
- uint8_t lines = items / itemsPerLine;
- if (items % itemsPerLine) lines++;
-
- for (i = 0; i < lines; i++)
- {
- for (k = 0; k < itemsPerLine; k++)
- {
- uint8_t j;
- uint8_t index = k * lines + i;
-
- if (index >= items) break;
-
- p("%3u = %s", index + 1, ExtendedProductList[index].name);
-
- for (j = 0; j < longestString + 4 - strlen(ExtendedProductList[index].name); j++)
- {
- p(" ");
- }
- }
-
- p("\n");
- }
-
- p("\n");
-
- #endif // !defined(NO_EXTENDED_PRODUCT_LIST) && !defined(NO_BASIC_PRODUCT_LIST)
-
- exit(0);
-}
-
-__noreturn static void examples(const char* const programName)
-{
- printf(
- "\nRequest activation for Office2013 using V4 protocol from 192.168.1.5:1688\n"
- "\t%s -l O15 -4 192.168.1.5\n"
- "\t%s -l O15 -4 192.168.1.5:1688\n\n"
-
- "Request activation for Windows Server 2012 using V4 protocol from localhost:1688\n"
- "\t%s -4 -l Windows -k 8665cb71-468c-4aa3-a337-cb9bc9d5eaac\n"
- "\t%s -4 -l 2012\n"
- "\t%s -4 -l 2012 [::1]:1688\n"
- "\t%s -4 -l 12 127.0.0.2:1688\n\n"
-
- "Send 100,000 requests to localhost:1688\n"
- "\t%s -n 100000 -l Office2010\n\n"
-
- "Request Activation for Windows 8 from 10.0.0.1:4711 and pretend to be Steve Ballmer\n"
- "\t%s -l Windows8 -w steveb1.redmond.microsoft.com 10.0.0.1:4711\n\n",
- programName, programName, programName, programName, programName, programName, programName, programName
- );
-
- exit(0);
-}
-
-
-#else // NO_HELP
-
-
-__noreturn static void clientUsage(const char* const programName)
-{
- errorout("Incorrect parameter specified.\n");
- exit(!0);
-}
-
-
-#endif // NO_HELP
-
-
-static BOOL findLicensePackByName(const char* const name, LicensePack* const lp)
-{
- // Try to find a package in the short list first
-
- LicensePack *licensePack;
- for (licensePack = (LicensePack*)&LicensePackList; licensePack->names; licensePack ++)
- {
- const char *currentName;
- for (currentName = licensePack->names; *currentName; currentName += strlen(currentName) + 1)
- {
- if (!strcasecmp(name, currentName))
- {
- *lp = *licensePack;
- return TRUE;
- }
- }
- }
-
- #if defined(NO_BASIC_PRODUCT_LIST) || defined(NO_EXTENDED_PRODUCT_LIST)
-
- return FALSE;
-
- #else // Both Lists are available
-
- // search extended product list
-
- uint8_t items = getExtendedProductListSize();
- unsigned int index;
-
- if (stringToInt(name, 1, items, &index))
- {
- index--;
- }
- else
- {
- for (index = 0; index < items; index++)
- {
- if (!strcasecmp(ExtendedProductList[index].name, name)) break;
- }
-
- if (index >= items) return FALSE;
- }
-
- lp->AppID = &AppList[ExtendedProductList[index].AppIndex].guid;
- lp->KMSID = ProductList[ExtendedProductList[index].KmsIndex].guid;
- lp->ActID = ExtendedProductList[index].guid;
- lp->N_Policy = ProductList[ExtendedProductList[index].KmsIndex].KMS_PARAM_REQUIREDCOUNT;
- lp->kmsVersionMajor = ProductList[ExtendedProductList[index].KmsIndex].KMS_PARAM_MAJOR;
-
- return TRUE;
-
- #endif // Both Lists are available
-}
-
-static const char* const client_optstring = "+N:B:i:l:a:s:k:c:w:r:n:t:g:G:o:pPTv456mexd";
-
-
-//First pass. We handle only "-l". Since -a -k -s -4 -5 and -6 are exceptions to -l, we process -l first
-static void parseCommandLinePass1(const int argc, CARGV argv)
-{
- int o;
- optReset();
-
- for (opterr = 0; ( o = getopt(argc, (char* const*)argv, client_optstring) ) > 0; ) switch (o)
- {
- case 'l': // Set "License Pack" and protocol version (e.g. Windows8, Office2013v5, ...)
-
- if (!findLicensePackByName(optarg, &ActiveLicensePack))
- {
- errorout("Invalid client application. \"%s\" is not valid for -l.\n\n", optarg);
- #ifndef NO_HELP
- showProducts(&errorout);
- #endif // !NO_HELP
- }
-
- break;
-
- default:
- break;
- }
-}
-
-
-// Second Pass. Handle all options except "-l"
-static void parseCommandLinePass2(const char *const programName, const int argc, CARGV argv)
-{
- int o;
- optReset();
-
- for (opterr = 0; ( o = getopt(argc, (char* const*)argv, client_optstring) ) > 0; ) switch (o)
- {
- #ifndef NO_HELP
-
- case 'e': // Show examples
-
- examples(programName);
- break;
-
- case 'x': // Show Apps
-
- showProducts(&printf);
- break;
-
- #endif // NO_HELP
-
-# ifndef NO_DNS
-
- case 'P':
-
- NoSrvRecordPriority = TRUE;
- break;
-
-# endif // NO_DNS
-
- case 'G':
-
- incompatibleOptions |= VLMCS_OPTION_GRAB_INI;
- fn_ini_client = optarg;
- break;
-
-# ifndef USE_MSRPC
-
- case 'N':
- if (!getArgumentBool(&UseRpcNDR64, optarg)) clientUsage(programName);
- break;
-
- case 'B':
- if (!getArgumentBool(&UseRpcBTFN, optarg)) clientUsage(programName);
- break;
-
- case 'i':
-
- switch(getOptionArgumentInt(o, 4, 6))
- {
- case 4:
- AddressFamily = AF_INET;
- break;
- case 6:
- AddressFamily = AF_INET6;
- break;
- default:
- errorout("IPv5 does not exist.\n");
- exit(!0);
- break;
- }
-
- break;
-
- case 'p': // Multiplexed RPC
-
- UseMultiplexedRpc = FALSE;
- break;
-
-# endif // USE_MSRPC
-
- case 'n': // Fixed number of Requests (regardless, whether they are required)
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- FixedRequests = getOptionArgumentInt(o, 1, INT_MAX);
- break;
-
- case 'r': // Fake minimum required client count
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- ActiveLicensePack.N_Policy = getOptionArgumentInt(o, 1, INT_MAX);
- break;
-
- case 'c': // use a specific client GUID
-
- // If using a constant Client ID, send only one request unless /N= explicitly specified
- if (!FixedRequests) FixedRequests = 1;
-
- CMID = optarg;
- break;
-
- case 'o': // use a specific previous client GUID
-
- CMID_prev = optarg;
- break;
-
- case 'a': // Set specific App Id
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- ActiveLicensePack.AppID = (GUID*)vlmcsd_malloc(sizeof(GUID));
-
- string2UuidOrExit(optarg, (GUID*)ActiveLicensePack.AppID);
- break;
-
- case 'g': // Set custom "grace" time in minutes (default 30 days)
-
- BindingExpiration = getOptionArgumentInt(o, 0, INT_MAX);
- break;
-
- case 's': // Set specfic SKU ID
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- string2UuidOrExit(optarg, &ActiveLicensePack.ActID);
- break;
-
- case 'k': // Set specific KMS ID
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- string2UuidOrExit(optarg, &ActiveLicensePack.KMSID);
- break;
-
- case '4': // Force V4 protocol
- case '5': // Force V5 protocol
- case '6': // Force V5 protocol
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- ActiveLicensePack.kmsVersionMajor = o - 0x30;
- break;
-
- case 'd': // Don't use DNS names
-
- dnsnames = FALSE;
- break;
-
- case 'v': // Be verbose
-
- verbose = TRUE;
- break;
-
- case 'm': // Pretend to be a virtual machine
-
- VMInfo = TRUE;
- break;
-
- case 'w': // WorkstationName (max. 63 chars)
-
- WorkstationName = optarg;
-
- if (strlen(WorkstationName) > 63)
- {
- errorout("\007WARNING! Truncating Workstation name to 63 characters (%s).\n", WorkstationName);
- }
-
- break;
-
- case 't':
-
- LicenseStatus = getOptionArgumentInt(o, 0, 6) & 0xff;
- break;
-
-# ifndef USE_MSRPC
-
- case 'T':
-
- ReconnectForEachRequest = TRUE;
- break;
-
-# endif // USE_MSRPC
-
- case 'l':
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- break;
-
- default:
- clientUsage(programName);
- }
- if ((incompatibleOptions & (VLMCS_OPTION_NO_GRAB_INI | VLMCS_OPTION_GRAB_INI)) == (VLMCS_OPTION_NO_GRAB_INI | VLMCS_OPTION_GRAB_INI))
- clientUsage(programName);
-}
-
-
-/*
- * Compares 2 GUIDs where one is host-endian and the other is little-endian (network byte order)
- */
-int_fast8_t IsEqualGuidLEHE(const GUID* const guid1, const GUID* const guid2)
-{
- GUID tempGuid;
- LEGUID(&tempGuid, guid2);
- return IsEqualGUID(guid1, &tempGuid);
-}
-
-
-#ifndef USE_MSRPC
-static void checkRpcLevel(const REQUEST* request, RESPONSE* response)
-{
- if (!RpcFlags.HasNDR32)
- errorout("\nWARNING: Server's RPC protocol does not support NDR32.\n");
-
- if (UseRpcBTFN && UseRpcNDR64 && RpcFlags.HasNDR64 && !RpcFlags.HasBTFN)
- errorout("\nWARNING: Server's RPC protocol has NDR64 but no BTFN.\n");
-
- if (!IsEqualGuidLEHE(&request->KMSID, &ProductList[15].guid) && UseRpcBTFN && !RpcFlags.HasBTFN)
- errorout("\nWARNING: A server with pre-Vista RPC activated a product other than Office 2010.\n");
-}
-#endif // USE_MSRPC
-
-
-static void displayResponse(const RESPONSE_RESULT result, const REQUEST* request, RESPONSE* response, BYTE *hwid)
-{
- fflush(stdout);
-
- if (!result.RpcOK) errorout("\n\007ERROR: Non-Zero RPC result code.\n");
- if (!result.DecryptSuccess) errorout("\n\007ERROR: Decryption of V5/V6 response failed.\n");
- if (!result.IVsOK) errorout("\n\007ERROR: AES CBC initialization vectors (IVs) of request and response do not match.\n");
- if (!result.PidLengthOK) errorout("\n\007ERROR: The length of the PID is not valid.\n");
- if (!result.HashOK) errorout("\n\007ERROR: Computed hash does not match hash in response.\n");
- if (!result.ClientMachineIDOK) errorout("\n\007ERROR: Client machine GUIDs of request and response do not match.\n");
- if (!result.TimeStampOK) errorout("\n\007ERROR: Time stamps of request and response do not match.\n");
- if (!result.VersionOK) errorout("\n\007ERROR: Protocol versions of request and response do not match.\n");
- if (!result.HmacSha256OK) errorout("\n\007ERROR: Keyed-Hash Message Authentication Code (HMAC) is incorrect.\n");
- if (!result.IVnotSuspicious) errorout("\nWARNING: Response uses an IV following KMSv5 rules in KMSv6 protocol.\n");
-
- if (result.effectiveResponseSize != result.correctResponseSize)
- {
- errorout("\n\007WARNING: Size of RPC payload (KMS Message) should be %u but is %u.", result.correctResponseSize, result.effectiveResponseSize);
- }
-
-# ifndef USE_MSRPC
- checkRpcLevel(request, response);
-# endif // USE_MSRPC
-
- if (!result.DecryptSuccess) return; // Makes no sense to display anything
-
- char ePID[3 * PID_BUFFER_SIZE];
- if (!ucs2_to_utf8(response->KmsPID, ePID, PID_BUFFER_SIZE, 3 * PID_BUFFER_SIZE))
- {
- memset(ePID + 3 * PID_BUFFER_SIZE - 3, 0, 3);
- }
-
- // Read KMSPID from Response
- if (!verbose)
- {
- printf(" -> %s", ePID);
-
- if (LE16(response->MajorVer) > 5)
- {
-# ifndef _WIN32
- printf(" (%016llX)", (unsigned long long)BE64(*(uint64_t*)hwid));
-# else // _WIN32
- printf(" (%016I64X)", (unsigned long long)BE64(*(uint64_t*)hwid));
-# endif // _WIN32
- }
-
- printf("\n");
- }
- else
- {
- printf(
- "\n\nResponse from KMS server\n========================\n\n"
- "Size of KMS Response : %u (0x%x)\n", result.effectiveResponseSize, result.effectiveResponseSize
- );
-
- logResponseVerbose(ePID, hwid, response, &printf);
- printf("\n");
- }
-}
-
-
-static void connectRpc(RpcCtx *s)
-{
-# ifdef NO_DNS
-
- *s = connectToAddress(RemoteAddr, AddressFamily, FALSE);
- if (*s == INVALID_RPCCTX)
- {
- errorout("Fatal: Could not connect to %s\n", RemoteAddr);
- exit(!0);
- }
-
- if (verbose)
- printf("\nPerforming RPC bind ...\n");
-
- if (rpcBindClient(*s, verbose))
- {
- errorout("Fatal: Could not bind RPC\n");
- exit(!0);
- }
-
- if (verbose) printf("... successful\n");
-
-# else // DNS
-
- static kms_server_dns_ptr* serverlist = NULL;
- static int numServers = 0;
- //static int_fast8_t ServerListAlreadyPrinted = FALSE;
- int i;
-
- if (!strcmp(RemoteAddr, "-") || *RemoteAddr == '.') // Get KMS server via DNS SRV record
- {
- if (!serverlist)
- numServers = getKmsServerList(&serverlist, RemoteAddr);
-
- if (numServers < 1)
- {
- errorout("Fatal: No KMS servers found\n");
- exit(!0);
- }
-
- if (!NoSrvRecordPriority) sortSrvRecords(serverlist, numServers);
-
- if (verbose /*&& !ServerListAlreadyPrinted*/)
- {
- for (i = 0; i < numServers; i++)
- {
- printf(
- "Found %-40s (priority: %hu, weight: %hu, randomized weight: %i)\n",
- serverlist[i]->serverName,
- serverlist[i]->priority, serverlist[i]->weight,
- NoSrvRecordPriority ? 0 : serverlist[i]->random_weight
- );
- }
-
- printf("\n");
- //ServerListAlreadyPrinted = TRUE;
- }
- }
- else // Just use the server supplied on the command line
- {
- if (!serverlist)
- {
- serverlist = (kms_server_dns_ptr*)vlmcsd_malloc(sizeof(kms_server_dns_ptr));
- *serverlist = (kms_server_dns_ptr)vlmcsd_malloc(sizeof(kms_server_dns_t));
-
- numServers = 1;
- strncpy((*serverlist)->serverName, RemoteAddr, sizeof((*serverlist)->serverName));
- }
- }
-
- for (i = 0; i < numServers; i++)
- {
- *s = connectToAddress(serverlist[i]->serverName, AddressFamily, (*RemoteAddr == '.' || *RemoteAddr == '-'));
-
- if (*s == INVALID_RPCCTX) continue;
-
- if (verbose)
- printf("\nPerforming RPC bind ...\n");
-
- if (rpcBindClient(*s, verbose))
- {
- errorout("Warning: Could not bind RPC\n");
- continue;
- }
-
- if (verbose) printf("... successful\n");
-
- return;
- }
-
- errorout("Fatal: Could not connect to any KMS server\n");
- exit(!0);
-
-# endif // DNS
-}
-
-
-static int SendActivationRequest(const RpcCtx sock, RESPONSE *baseResponse, REQUEST *baseRequest, RESPONSE_RESULT *result, BYTE *const hwid)
-{
- size_t requestSize, responseSize;
- BYTE *request, *response;
- int status;
-
- result->mask = 0;
-
- if (LE16(baseRequest->MajorVer) == 4)
- request = CreateRequestV4(&requestSize, baseRequest);
- else
- request = CreateRequestV6(&requestSize, baseRequest);
-
- if (!(status = rpcSendRequest(sock, request, requestSize, &response, &responseSize)))
- {
- if (LE16(((RESPONSE*)(response))->MajorVer) == 4)
- {
- RESPONSE_V4 response_v4;
- *result = DecryptResponseV4(&response_v4, responseSize, response, request);
- memcpy(baseResponse, &response_v4.ResponseBase, sizeof(RESPONSE));
- }
- else
- {
- RESPONSE_V6 response_v6;
- *result = DecryptResponseV6(&response_v6, responseSize, response, request, hwid);
- memcpy(baseResponse, &response_v6.ResponseBase, sizeof(RESPONSE));
- }
-
- result->RpcOK = TRUE;
- }
-
- if (response) free(response);
- free(request);
- return status;
-}
-
-
-static int sendRequest(RpcCtx *const s, REQUEST *const request, RESPONSE *const response, hwid_t hwid, RESPONSE_RESULT *const result)
-{
- CreateRequestBase(request);
-
- if (*s == INVALID_RPCCTX )
- connectRpc(s);
- else
- {
- // Check for lame KMS emulators that close the socket after each request
- int_fast8_t disconnected = isDisconnected(*s);
-
- if (disconnected)
- errorout("\nWarning: Server closed RPC connection (probably non-multitasked KMS emulator)\n");
-
- if (ReconnectForEachRequest || disconnected)
- {
- closeRpc(*s);
- connectRpc(s);
- }
- }
-
- printf("Sending activation request (KMS V%u) ", ActiveLicensePack.kmsVersionMajor);
- fflush(stdout);
-
- return SendActivationRequest(*s, response, request, result, hwid);
-}
-
-
-static void displayRequestError(RpcCtx *const s, const int status, const int currentRequest, const int totalRequests)
-{
- errorout("\nError 0x%08X while sending request %u of %u\n", status, currentRequest, RequestsToGo + totalRequests);
-
- switch(status)
- {
- case 0xC004F042: // not licensed
- errorout("The server refused to activate the requested product\n");
- break;
-
- case 0x8007000D: // e.g. v6 protocol on a v5 server
- errorout("The server didn't understand the request\n");
- break;
-
- case 1:
- errorout("An RPC protocol error has occured\n");
- closeRpc(*s);
- connectRpc(s);
- break;
-
- default:
- break;
- }
-}
-
-
-static void newIniBackupFile(const char* const restrict fname)
-{
- FILE *restrict f = fopen(fname, "wb");
-
- if (!f)
- {
- errorout("Fatal: Cannot create %s: %s\n", fname, strerror(errno));
- exit(!0);
- }
-
- if (fclose(f))
- {
- errorout("Fatal: Cannot write to %s: %s\n", fname, strerror(errno));
- unlink(fname);
- exit(!0);
- }
-}
-
-
-static void updateIniFile(iniFileEpidLines* const restrict lines)
-{
- int_fast8_t lineWritten[_countof(*lines)];
- struct stat statbuf;
- uint_fast8_t i;
- int_fast8_t iniFileExistedBefore = TRUE;
- unsigned int lineNumber;
-
- memset(lineWritten, FALSE, sizeof(lineWritten));
-
- char* restrict fn_bak = (char*)vlmcsd_malloc(strlen(fn_ini_client) + 2);
-
- strcpy(fn_bak, fn_ini_client);
- strcat(fn_bak, "~");
-
- if (stat(fn_ini_client, &statbuf))
- {
- if (errno != ENOENT)
- {
- errorout("Fatal: %s: %s\n", fn_ini_client, strerror(errno));
- exit(!0);
- }
- else
- {
- iniFileExistedBefore = FALSE;
- newIniBackupFile(fn_bak);
- }
- }
- else
- {
- unlink(fn_bak); // Required for Windows. Most Unix systems don't need it.
- if (rename(fn_ini_client, fn_bak))
- {
- errorout("Fatal: Cannot create %s: %s\n", fn_bak, strerror(errno));
- exit(!0);
- }
- }
-
- printf("\n%s file %s\n", iniFileExistedBefore ? "Updating" : "Creating", fn_ini_client);
-
- FILE *restrict in, *restrict out;
-
- in = fopen(fn_bak, "rb");
-
- if (!in)
- {
- errorout("Fatal: Cannot open %s: %s\n", fn_bak, strerror(errno));
- exit(!0);
- }
-
- out = fopen(fn_ini_client, "wb");
-
- if (!out)
- {
- errorout("Fatal: Cannot create %s: %s\n", fn_ini_client, strerror(errno));
- exit(!0);
- }
-
- char sourceLine[256];
-
- for (lineNumber = 1; fgets(sourceLine, sizeof(sourceLine), in); lineNumber++)
- {
- for (i = 0; i < _countof(*lines); i++)
- {
- if (*(*lines)[i] && !strncasecmp(sourceLine, (*lines)[i], GUID_STRING_LENGTH))
- {
- if (lineWritten[i]) break;
-
- fprintf(out, "%s", (*lines)[i]);
- printf("line %2i: %s", lineNumber, (*lines)[i]);
- lineWritten[i] = TRUE;
- break;
- }
- }
-
- if (i >= _countof(*lines))
- {
- fprintf(out, "%s", sourceLine);
- }
- }
-
- if (ferror(in))
- {
- errorout("Fatal: Cannot read from %s: %s\n", fn_bak, strerror(errno));
- exit(!0);
- }
-
- fclose(in);
-
- for (i = 0; i < _countof(*lines); i++)
- {
- if (!lineWritten[i] && *(*lines)[i])
- {
- fprintf(out, "%s", (*lines)[i]);
- printf("line %2i: %s", lineNumber + i, (*lines)[i]);
- }
- }
-
- if (fclose(out))
- {
- errorout("Fatal: Cannot write to %s: %s\n", fn_ini_client, strerror(errno));
- exit(!0);
- }
-
- if (!iniFileExistedBefore) unlink(fn_bak);
-
- free(fn_bak);
-}
-
-static void grabServerData()
-{
- RpcCtx s = INVALID_RPCCTX;
- WORD MajorVer = 6;
- iniFileEpidLines lines;
- int_fast8_t Licenses[_countof(lines)] = { 0, 15, 14 };
- uint_fast8_t i;
- RESPONSE response;
- RESPONSE_RESULT result;
- REQUEST request;
- hwid_t hwid;
- int status;
- size_t len;
-
- for (i = 0; i < _countof(lines); i++) *lines[i] = 0;
-
- for (i = 0; i < _countof(Licenses) && MajorVer > 3; i++)
- {
- ActiveLicensePack = LicensePackList[Licenses[i]];
- ActiveLicensePack.kmsVersionMajor = MajorVer;
- status = sendRequest(&s, &request, &response, hwid, &result);
- printf("%-11s", ActiveLicensePack.names);
-
- if (status)
- {
- displayRequestError(&s, status, i + 7 - MajorVer, 9 - MajorVer);
-
- if (status == 1) break;
-
- if ((status & 0xF0000000) == 0x80000000)
- {
- MajorVer--;
- i--;
- }
-
- continue;
- }
-
- printf("%i of %i", (int)(i + 7 - MajorVer), (int)(9 - MajorVer));
- displayResponse(result, &request, &response, hwid);
-
- char guidBuffer[GUID_STRING_LENGTH + 1];
- char ePID[3 * PID_BUFFER_SIZE];
-
- uuid2StringLE(&request.AppID, guidBuffer);
-
- if (!ucs2_to_utf8(response.KmsPID, ePID, PID_BUFFER_SIZE, 3 * PID_BUFFER_SIZE))
- {
- memset(ePID + 3 * PID_BUFFER_SIZE - 3, 0, 3);
- }
-
- snprintf(lines[i], sizeof(lines[0]), "%s = %s", guidBuffer, ePID);
-
- if (response.MajorVer > 5)
- {
- len = strlen(lines[i]);
- 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]);
- }
-
- len = strlen(lines[i]);
- snprintf(lines[i] + len, sizeof(lines[0]) - len, "\n");
-
- }
-
- if (strcmp(fn_ini_client, "-"))
- {
- updateIniFile(&lines);
- }
- else
- {
- printf("\n");
- for (i = 0; i < _countof(lines); i++) printf("%s", lines[i]);
- }
-}
-
-
-int client_main(const int argc, CARGV argv)
-{
- #if defined(_WIN32) && !defined(USE_MSRPC)
-
- // Windows Sockets must be initialized
-
- WSADATA wsadata;
- int error;
-
- if ((error = WSAStartup(0x0202, &wsadata)))
- {
- printerrorf("Fatal: Could not initialize Windows sockets (Error: %d).\n", error);
- return error;
- }
-
- #endif // _WIN32
-
- #ifdef _NTSERVICE
-
- // We are not a service
- IsNTService = FALSE;
-
- // Set console output page to UTF-8
- // SetConsoleOutputCP(65001);
-
- #endif // _NTSERVICE
-
- randomNumberInit();
- ActiveLicensePack = *LicensePackList; //first license is Windows Vista
-
- parseCommandLinePass1(argc, argv);
-
- int_fast8_t useDefaultHost = FALSE;
-
- if (optind < argc)
- RemoteAddr = argv[optind];
- else
- useDefaultHost = TRUE;
-
- int hostportarg = optind;
-
- if (optind < argc - 1)
- {
- parseCommandLinePass1(argc - hostportarg, argv + hostportarg);
-
- if (optind < argc - hostportarg)
- clientUsage(argv[0]);
- }
-
- parseCommandLinePass2(argv[0], argc, argv);
-
- if (optind < argc - 1)
- parseCommandLinePass2(argv[0], argc - hostportarg, argv + hostportarg);
-
- if (useDefaultHost)
- RemoteAddr = AddressFamily == AF_INET6 ? "::1" : "127.0.0.1";
-
- if (fn_ini_client != NULL)
- grabServerData();
- else
- {
- int requests;
- RpcCtx s = INVALID_RPCCTX;
-
- for (requests = 0, RequestsToGo = ActiveLicensePack.N_Policy - 1; RequestsToGo; requests++)
- {
- RESPONSE response;
- REQUEST request;
- RESPONSE_RESULT result;
- hwid_t hwid;
-
- int status = sendRequest(&s, &request, &response, hwid, &result);
-
- if (FixedRequests) RequestsToGo = FixedRequests - requests - 1;
-
- if (status)
- {
- displayRequestError(&s, status, requests + 1, RequestsToGo + requests + 1);
- if (!FixedRequests) RequestsToGo = 0;
- }
- else
- {
- if (!FixedRequests)
- {
- if (firstRequestSent && ActiveLicensePack.N_Policy - (int)response.Count >= RequestsToGo)
- {
- errorout("\nThe KMS server does not increment it's active clients. Aborting...\n");
- RequestsToGo = 0;
- }
- else
- {
- RequestsToGo = ActiveLicensePack.N_Policy - response.Count;
- if (RequestsToGo < 0) RequestsToGo = 0;
- }
- }
-
- fflush(stderr);
- printf("%i of %i ", requests + 1, RequestsToGo + requests + 1);
- displayResponse(result, &request, &response, hwid);
- firstRequestSent = TRUE;
- }
- }
- }
-
- return 0;
-}
-
-
-// Create Base KMS Client Request
-static void CreateRequestBase(REQUEST *Request)
-{
-
- Request->MinorVer = LE16((WORD)kmsVersionMinor);
- Request->MajorVer = LE16((WORD)ActiveLicensePack.kmsVersionMajor);
- Request->VMInfo = LE32(VMInfo);
- Request->LicenseStatus = LE32(LicenseStatus);
- Request->BindingExpiration = LE32(BindingExpiration);
- LEGUID(&Request->AppID, ActiveLicensePack.AppID);
- LEGUID(&Request->ActID, &ActiveLicensePack.ActID);
- LEGUID(&Request->KMSID, &ActiveLicensePack.KMSID);
-
- getUnixTimeAsFileTime(&Request->ClientTime);
- Request->N_Policy = LE32(ActiveLicensePack.N_Policy);
-
- {
- GUID tempGUID;
-
- if (CMID)
- {
- string2UuidOrExit(CMID, &tempGUID);
- LEGUID(&Request->CMID, &tempGUID);
- }
- else
- {
- get16RandomBytes(&Request->CMID);
-
- // Set reserved UUID bits
- Request->CMID.Data4[0] &= 0x3F;
- Request->CMID.Data4[0] |= 0x80;
-
- // Set UUID type 4 (random UUID)
- Request->CMID.Data3 &= LE16(0xfff);
- Request->CMID.Data3 |= LE16(0x4000);
- }
-
- if (CMID_prev)
- {
- string2UuidOrExit(CMID_prev, &tempGUID);
- LEGUID(&Request->CMID_prev, &tempGUID);
- }
- else
- {
- memset(&Request->CMID_prev, 0, sizeof(Request->CMID_prev));
- }
- }
-
- static const char alphanum[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /*"abcdefghijklmnopqrstuvwxyz" */;
-
- if (WorkstationName)
- {
- utf8_to_ucs2(Request->WorkstationName, WorkstationName, WORKSTATION_NAME_BUFFER, WORKSTATION_NAME_BUFFER * 3);
- }
- else if (dnsnames)
- {
- int len, len2;
- unsigned int index = rand() % _countof(ClientDnsNames.first);
- len = utf8_to_ucs2(Request->WorkstationName, ClientDnsNames.first[index], WORKSTATION_NAME_BUFFER, WORKSTATION_NAME_BUFFER * 3);
-
- index = rand() % _countof(ClientDnsNames.second);
- len2 = utf8_to_ucs2(Request->WorkstationName + len, ClientDnsNames.second[index], WORKSTATION_NAME_BUFFER, WORKSTATION_NAME_BUFFER * 3);
-
- index = rand() % _countof(ClientDnsNames.tld);
- utf8_to_ucs2(Request->WorkstationName + len + len2, ClientDnsNames.tld[index], WORKSTATION_NAME_BUFFER, WORKSTATION_NAME_BUFFER * 3);
- }
- else
- {
- unsigned int size = (rand() % 14) + 1;
- const unsigned char *dummy;
- unsigned int i;
-
- for (i = 0; i < size; i++)
- {
- Request->WorkstationName[i] = utf8_to_ucs2_char((unsigned char*)alphanum + (rand() % (sizeof(alphanum) - 1)), &dummy);
- }
-
- Request->WorkstationName[size] = 0;
- }
-
- //Show Details
- if (verbose)
- {
- printf("\nRequest Parameters\n==================\n\n");
- logRequestVerbose(Request, &printf);
- printf("\n");
- }
-}
-
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "crypto.h"
-#include "endian.h"
-#include
-
-const BYTE AesKeyV4[] = {
- 0x05, 0x3D, 0x83, 0x07, 0xF9, 0xE5, 0xF0, 0x88, 0xEB, 0x5E, 0xA6, 0x68, 0x6C, 0xF0, 0x37, 0xC7, 0xE4, 0xEF, 0xD2, 0xD6};
-
-const BYTE AesKeyV5[] = {
- 0xCD, 0x7E, 0x79, 0x6F, 0x2A, 0xB2, 0x5D, 0xCB, 0x55, 0xFF, 0xC8, 0xEF, 0x83, 0x64, 0xC4, 0x70 };
-
-const BYTE AesKeyV6[] = {
- 0xA9, 0x4A, 0x41, 0x95, 0xE2, 0x01, 0x43, 0x2D, 0x9B, 0xCB, 0x46, 0x04, 0x05, 0xD8, 0x4A, 0x21 };
-
-static const BYTE SBox[] = {
- 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
- 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
- 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
- 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
- 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
- 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
- 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
- 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
- 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
- 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
- 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
- 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
- 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
- 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
- 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
- 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
- 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
- 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
- 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
- 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
- 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
- 0xB0, 0x54, 0xBB, 0x16
-};
-
-
-void XorBlock(const BYTE *const in, const BYTE *out) // Ensure that this is always 32 bit aligned
-{
- /*UAA64( out, 0 ) ^= UAA64( in, 0 );
- UAA64( out, 1 ) ^= UAA64( in, 1 );*/
-
- uint_fast8_t i;
-
- for (i = 0; i < AES_BLOCK_WORDS; i++)
- {
- ((DWORD*)out)[i] ^= ((DWORD*)in)[i];
- }
-}
-
-#define AddRoundKey(d, rk) XorBlock((const BYTE *)rk, (const BYTE *)d)
-
-#define Mul2(word) (((word & 0x7f7f7f7f) << 1) ^ (((word & 0x80808080) >> 7) * 0x1b))
-#define Mul3(word) (Mul2(word) ^ word)
-#define Mul4(word) (Mul2(Mul2(word)))
-#define Mul8(word) (Mul2(Mul2(Mul2(word))))
-#define Mul9(word) (Mul8(word) ^ word)
-#define MulB(word) (Mul8(word) ^ Mul3(word))
-#define MulD(word) (Mul8(word) ^ Mul4(word) ^ word)
-#define MulE(word) (Mul8(word) ^ Mul4(word) ^ Mul2(word))
-
-//32 bit Galois Multiplication (generates bigger code than Macros)
-/*static DWORD Mul(DWORD x, DWORD y)
-{
- DWORD result = x, yTemp = y, log2;
-
- if (!y) return 0;
-
- for (log2 = 0; yTemp >>= 1; log2++ )
- {
- result = Mul2(result);
- }
-
- return result ^ Mul(x, y - (1 << log2));
-}*/
-
-
-void MixColumnsR(BYTE *restrict state)
-{
- uint_fast8_t i = 0;
- for (; i < AES_BLOCK_WORDS; i++)
- {
- #if defined(_CRYPTO_OPENSSL) && defined(_OPENSSL_SOFTWARE) && defined(_USE_AES_FROM_OPENSSL) //Always byte swap regardless of endianess
- DWORD word = BS32(((DWORD *) state)[i]);
- ((DWORD *) state)[i] = BS32(MulE(word) ^ ROR32(MulB(word), 8) ^ ROR32(MulD(word), 16) ^ ROR32(Mul9(word), 24));
- #else
- DWORD word = LE32(((DWORD *) state)[i]);
- ((DWORD *) state)[i] = LE32(MulE(word) ^ ROR32(MulB(word), 8) ^ ROR32(MulD(word), 16) ^ ROR32(Mul9(word), 24));
- #endif
- }
-}
-
-
-static DWORD SubDword(DWORD v)
-{
- BYTE *b = (BYTE *)&v;
- uint_fast8_t i = 0;
-
- for (; i < sizeof(DWORD); i++) b[i] = SBox[b[i]];
-
- return v;
-}
-
-
-void AesInitKey(AesCtx *Ctx, const BYTE *Key, int_fast8_t IsV6, int RijndaelKeyBytes)
-{
- int RijndaelKeyDwords = RijndaelKeyBytes / sizeof(DWORD);
- Ctx->rounds = (uint_fast8_t)(RijndaelKeyDwords + 6);
-
- static const DWORD RCon[] = {
- 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
- 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000 };
-
- uint_fast8_t i;
- DWORD temp;
-
- memcpy(Ctx->Key, Key, RijndaelKeyBytes);
-
- for ( i = RijndaelKeyDwords; i < ( Ctx->rounds + 1 ) << 2; i++ )
- {
- temp = Ctx->Key[ i - 1 ];
-
- if ( ( i % RijndaelKeyDwords ) == 0 )
- temp = BE32( SubDword( ROR32( BE32(temp), 24) ) ^ RCon[ i / RijndaelKeyDwords ] );
-
- Ctx->Key[ i ] = Ctx->Key[ i - RijndaelKeyDwords ] ^ temp;
- }
-
- if ( IsV6 )
- {
- BYTE *_p = (BYTE *)Ctx->Key;
-
- _p[ 4 * 16 ] ^= 0x73;
- _p[ 6 * 16 ] ^= 0x09;
- _p[ 8 * 16 ] ^= 0xE4;
- }
-}
-
-
-#if !defined(_CRYPTO_OPENSSL) || !defined(_USE_AES_FROM_OPENSSL) || defined(_OPENSSL_SOFTWARE)
-static void SubBytes(BYTE *block)
-{
- uint_fast8_t i;
-
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- block[i] = SBox[ block[i] ];
-}
-
-
-static void ShiftRows(BYTE *state)
-{
- BYTE bIn[AES_BLOCK_BYTES];
- uint_fast8_t i;
-
- memcpy(bIn, state, AES_BLOCK_BYTES);
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- {
- state[i] = bIn[(i + ((i & 3) << 2)) & 0xf];
- }
-};
-
-
-static void MixColumns(BYTE *state)
-{
- uint_fast8_t i = 0;
- for (; i < AES_BLOCK_WORDS; i++)
- {
- DWORD word = LE32(((DWORD *) state)[i]);
- ((DWORD *) state)[i] = LE32(Mul2(word) ^ ROR32(Mul3(word), 8) ^ ROR32(word, 16) ^ ROR32(word, 24));
- }
-}
-
-
-void AesEncryptBlock(const AesCtx *const Ctx, BYTE *block)
-{
- uint_fast8_t i;
-
- for ( i = 0 ;; i += 4 )
- {
- AddRoundKey(block, &Ctx->Key[ i ]);
- SubBytes(block);
- ShiftRows(block);
-
- if ( i >= ( Ctx->rounds - 1 ) << 2 ) break;
-
- MixColumns(block);
- }
-
- AddRoundKey(block, &Ctx->Key[ Ctx->rounds << 2 ]);
-}
-
-
-void AesCmacV4(BYTE *Message, size_t MessageSize, BYTE *MacOut)
-{
- size_t i;
- BYTE mac[AES_BLOCK_BYTES];
- AesCtx Ctx;
-
- AesInitKey(&Ctx, AesKeyV4, FALSE, V4_KEY_BYTES);
-
- memset(mac, 0, sizeof(mac));
- memset(Message + MessageSize, 0, AES_BLOCK_BYTES);
- Message[MessageSize] = 0x80;
-
- for (i = 0; i <= MessageSize; i += AES_BLOCK_BYTES)
- {
- XorBlock(Message + i, mac);
- AesEncryptBlock(&Ctx, mac);
- }
-
- memcpy(MacOut, mac, AES_BLOCK_BYTES);
-}
-#endif
-
-#if !defined(_CRYPTO_OPENSSL) || !defined(_USE_AES_FROM_OPENSSL)
-
-static const BYTE SBoxR[] = {
- 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,
- 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
- 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,
- 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
- 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,
- 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
- 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
- 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
- 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,
- 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
- 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
- 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
- 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,
- 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
- 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,
- 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
- 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,
- 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
- 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,
- 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
- 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
- 0x55, 0x21, 0x0C, 0x7D
-};
-
-
-static void ShiftRowsR(BYTE *state)
-{
- BYTE b[AES_BLOCK_BYTES];
- uint_fast8_t i;
-
- memcpy(b, state, AES_BLOCK_BYTES);
-
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- state[i] = b[(i - ((i & 0x3) << 2)) & 0xf];
-}
-
-
-static void SubBytesR(BYTE *block)
-{
- uint_fast8_t i;
-
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- block[i] = SBoxR[ block[i] ];
-}
-
-
-void AesEncryptCbc(const AesCtx *const Ctx, BYTE *restrict iv, BYTE *restrict data, size_t *restrict len)
-{
- // Pad up to blocksize inclusive
- size_t i;
- uint_fast8_t pad = (~*len & (AES_BLOCK_BYTES - 1)) + 1;
-
- #if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ == 8) // gcc 4.8 memset bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56977
- for (i = 0; i < pad; i++) data[*len + i] = pad;
- #else
- memset(data + *len, pad, pad);
- #endif
- *len += pad;
-
- if ( iv ) XorBlock(iv, data);
- AesEncryptBlock(Ctx, data);
-
- for (i = *len - AES_BLOCK_BYTES; i; i -= AES_BLOCK_BYTES)
- {
- XorBlock(data, data + AES_BLOCK_BYTES);
- data += AES_BLOCK_BYTES;
- AesEncryptBlock(Ctx, data);
- }
-}
-
-
-void AesDecryptBlock(const AesCtx *const Ctx, BYTE *block)
-{
- uint_fast8_t i;
-
- AddRoundKey(block, &Ctx->Key[ Ctx->rounds << 2 ]);
-
- for ( i = ( Ctx->rounds - 1 ) << 2 ;; i -= 4 )
- {
- ShiftRowsR(block);
- SubBytesR(block);
- AddRoundKey(block, &Ctx->Key[ i ]);
-
- if ( i == 0 ) break;
-
- MixColumnsR(block);
- }
-}
-
-
-void AesDecryptCbc(const AesCtx *const Ctx, BYTE *iv, BYTE *data, size_t len)
-{
- BYTE *cc;
-
- for (cc = data + len - AES_BLOCK_BYTES; cc > data; cc -= AES_BLOCK_BYTES)
- {
- AesDecryptBlock(Ctx, cc);
- XorBlock(cc - AES_BLOCK_BYTES, cc);
- }
-
- AesDecryptBlock(Ctx, cc);
- if ( iv ) XorBlock(iv, cc);
-}
-#endif // _CRYPTO_OPENSSL || OPENSSL_VERSION_NUMBER < 0x10000000L
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include
-#include
-#include
-#include
-#include
-#if !defined(_WIN32)
-#include
-#endif
-
-#include "output.h"
-#include "crypto.h"
-#include "endian.h"
-#include "kms.h"
-#include "shared_globals.h"
-#include "helpers.h"
-
-#define FRIENDLY_NAME_WINDOWS "Windows"
-#define FRIENDLY_NAME_OFFICE2010 "Office 2010"
-#define FRIENDLY_NAME_OFFICE2013 "Office"
-
-#ifndef NO_BASIC_PRODUCT_LIST
-// Do not change the order of this list. Append items as necessary
-const KmsIdList ProductList[] = {
- /* 000 */ { { 0x212a64dc, 0x43b1, 0x4d3d, { 0xa3, 0x0c, 0x2f, 0xc6, 0x9d, 0x20, 0x95, 0xc6 } } /*"212a64dc-43b1-4d3d-a30c-2fc69d2095c6"*/, "Vista", EPID_WINDOWS, 4, 25 },
- /* 001 */ { { 0x7fde5219, 0xfbfa, 0x484a, { 0x82, 0xc9, 0x34, 0xd1, 0xad, 0x53, 0xe8, 0x56 } } /*"7fde5219-fbfa-484a-82c9-34d1ad53e856"*/, "Windows 7", EPID_WINDOWS, 4, 25 },
- /* 002 */ { { 0x3c40b358, 0x5948, 0x45af, { 0x92, 0x3b, 0x53, 0xd2, 0x1f, 0xcc, 0x7e, 0x79 } } /*"3c40b358-5948-45af-923b-53d21fcc7e79"*/, "Windows 8 VL", EPID_WINDOWS, 5, 25 },
- /* 003 */ { { 0x5f94a0bb, 0xd5a0, 0x4081, { 0xa6, 0x85, 0x58, 0x19, 0x41, 0x8b, 0x2f, 0xe0 } } /*"5f94a0bb-d5a0-4081-a685-5819418b2fe0"*/, "Windows Preview", EPID_WINDOWS, 6, 25 },
- /* 004 */ { { 0xbbb97b3b, 0x8ca4, 0x4a28, { 0x97, 0x17, 0x89, 0xfa, 0xbd, 0x42, 0xc4, 0xac } } /*"bbb97b3b-8ca4-4a28-9717-89fabd42c4ac"*/, "Windows 8 Retail", EPID_WINDOWS, 5, 25 },
- /* 005 */ { { 0xcb8fc780, 0x2c05, 0x495a, { 0x97, 0x10, 0x85, 0xaf, 0xff, 0xc9, 0x04, 0xd7 } } /*"cb8fc780-2c05-495a-9710-85afffc904d7"*/, "Windows 8.1 VL", EPID_WINDOWS, 6, 25 },
- /* 006 */ { { 0x6d646890, 0x3606, 0x461a, { 0x86, 0xab, 0x59, 0x8b, 0xb8, 0x4a, 0xce, 0x82 } } /*"6d646890-3606-461a-86ab-598bb84ace82"*/, "Windows 8.1 Retail", EPID_WINDOWS, 6, 25 },
- /* 007 */ { { 0x33e156e4, 0xb76f, 0x4a52, { 0x9f, 0x91, 0xf6, 0x41, 0xdd, 0x95, 0xac, 0x48 } } /*"33e156e4-b76f-4a52-9f91-f641dd95ac48"*/, "Windows 2008 A", EPID_WINDOWS, 4, 5 },
- /* 008 */ { { 0x8fe53387, 0x3087, 0x4447, { 0x89, 0x85, 0xf7, 0x51, 0x32, 0x21, 0x5a, 0xc9 } } /*"8fe53387-3087-4447-8985-f75132215ac9"*/, "Windows 2008 B", EPID_WINDOWS, 4, 5 },
- /* 009 */ { { 0x8a21fdf3, 0xcbc5, 0x44eb, { 0x83, 0xf3, 0xfe, 0x28, 0x4e, 0x66, 0x80, 0xa7 } } /*"8a21fdf3-cbc5-44eb-83f3-fe284e6680a7"*/, "Windows 2008 C", EPID_WINDOWS, 4, 5 },
- /* 010 */ { { 0x0fc6ccaf, 0xff0e, 0x4fae, { 0x9d, 0x08, 0x43, 0x70, 0x78, 0x5b, 0xf7, 0xed } } /*"0fc6ccaf-ff0e-4fae-9d08-4370785bf7ed"*/, "Windows 2008 R2 A", EPID_WINDOWS, 4, 5 },
- /* 011 */ { { 0xca87f5b6, 0xcd46, 0x40c0, { 0xb0, 0x6d, 0x8e, 0xcd, 0x57, 0xa4, 0x37, 0x3f } } /*"ca87f5b6-cd46-40c0-b06d-8ecd57a4373f"*/, "Windows 2008 R2 B", EPID_WINDOWS, 4, 5 },
- /* 012 */ { { 0xb2ca2689, 0xa9a8, 0x42d7, { 0x93, 0x8d, 0xcf, 0x8e, 0x9f, 0x20, 0x19, 0x58 } } /*"b2ca2689-a9a8-42d7-938d-cf8e9f201958"*/, "Windows 2008 R2 C", EPID_WINDOWS, 4, 5 },
- /* 013 */ { { 0x8665cb71, 0x468c, 0x4aa3, { 0xa3, 0x37, 0xcb, 0x9b, 0xc9, 0xd5, 0xea, 0xac } } /*"8665cb71-468c-4aa3-a337-cb9bc9d5eaac"*/, "Windows 2012", EPID_WINDOWS, 5, 5 },
- /* 014 */ { { 0x8456EFD3, 0x0C04, 0x4089, { 0x87, 0x40, 0x5b, 0x72, 0x38, 0x53, 0x5a, 0x65 } } /*"8456EFD3-0C04-4089-8740-5B7238535A65"*/, "Windows 2012 R2", EPID_WINDOWS, 6, 5 },
- /* 015 */ { { 0xe85af946, 0x2e25, 0x47b7, { 0x83, 0xe1, 0xbe, 0xbc, 0xeb, 0xea, 0xc6, 0x11 } } /*"e85af946-2e25-47b7-83e1-bebcebeac611"*/, "Office 2010", EPID_OFFICE2010, 4, 5 },
- /* 016 */ { { 0xe6a6f1bf, 0x9d40, 0x40c3, { 0xaa, 0x9f, 0xc7, 0x7b, 0xa2, 0x15, 0x78, 0xc0 } } /*"e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0"*/, "Office 2013", EPID_OFFICE2013, 6, 5 },
- /* 017 */ { { 0x6d5f5270, 0x31ac, 0x433e, { 0xb9, 0x0a, 0x39, 0x89, 0x29, 0x23, 0xc6, 0x57 } } /*"6d5f5270-31ac-433e-b90a-39892923c657"*/, "Windows Server Preview", EPID_WINDOWS, 6, 5 },
- /* 018 */ { { 0x85b5f61b, 0x320b, 0x4be3, { 0x81, 0x4a, 0xb7, 0x6b, 0x2b, 0xfa, 0xfc, 0x82 } } /*"85b5f61b-320b-4be3-814a-b76b2bfafc82"*/, "Office 2016", EPID_OFFICE2013, 6, 5 },
- /* 019 */ { { 0x58e2134f, 0x8e11, 0x4d17, { 0x9c, 0xb2, 0x91, 0x06, 0x9c, 0x15, 0x11, 0x48 } } /*"58e2134f-8e11-4d17-9cb2-91069c151148"*/, "Windows 10 VL", EPID_WINDOWS, 6, 25 },
- /* 020 */ { { 0xe1c51358, 0xfe3e, 0x4203, { 0xa4, 0xa2, 0x3b, 0x6b, 0x20, 0xc9, 0x73, 0x4e } } /*"e1c51358-fe3e-4203-a4a2-3b6b20c9734e"*/, "Windows 10 Retail", EPID_WINDOWS, 6, 25 },
- /* 021 */ { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
-};
-#endif
-
-// Application ID is used by KMS server to count KeyManagementServiceCurrentCount
-// Do not change the order of this list. Append items as necessary
-const KmsIdList AppList[] = {
- /* 000 */ { { 0x55c92734, 0xd682, 0x4d71, { 0x98, 0x3e, 0xd6, 0xec, 0x3f, 0x16, 0x05, 0x9f } } /*"55C92734-D682-4D71-983E-D6EC3F16059F"*/, FRIENDLY_NAME_WINDOWS, EPID_WINDOWS, 0, 0},
- /* 001 */ { { 0x59A52881, 0xa989, 0x479d, { 0xaf, 0x46, 0xf2, 0x75, 0xc6, 0x37, 0x06, 0x63 } } /*"59A52881-A989-479D-AF46-F275C6370663"*/, FRIENDLY_NAME_OFFICE2010, EPID_OFFICE2010, 0, 0},
- /* 002 */ { { 0x0FF1CE15, 0xA989, 0x479D, { 0xaf, 0x46, 0xf2, 0x75, 0xc6, 0x37, 0x06, 0x63 } } /*"0FF1CE15-A989-479D-AF46-F275C6370663"*/, FRIENDLY_NAME_OFFICE2013, EPID_OFFICE2013, 0, 0},
- /* 003 */ { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
-};
-
-#ifndef NO_EXTENDED_PRODUCT_LIST
-const KmsIdList ExtendedProductList [] = {
-
- // Windows Server
-
- { { 0xad2542d4, 0x9154, 0x4c6d, { 0x8a, 0x44, 0x30, 0xf1, 0x1e, 0xe9, 0x69, 0x89, } } /*ad2542d4-9154-4c6d-8a44-30f11ee96989*/, "Windows Server 2008 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008A },
- { { 0x2401e3d0, 0xc50a, 0x4b58, { 0x87, 0xb2, 0x7e, 0x79, 0x4b, 0x7d, 0x26, 0x07, } } /*2401e3d0-c50a-4b58-87b2-7e794b7d2607*/, "Windows Server 2008 Standard V", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008A },
- { { 0x68b6e220, 0xcf09, 0x466b, { 0x92, 0xd3, 0x45, 0xcd, 0x96, 0x4b, 0x95, 0x09, } } /*68b6e220-cf09-466b-92d3-45cd964b9509*/, "Windows Server 2008 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008C },
- { { 0xfd09ef77, 0x5647, 0x4eff, { 0x80, 0x9c, 0xaf, 0x2b, 0x64, 0x65, 0x9a, 0x45, } } /*fd09ef77-5647-4eff-809c-af2b64659a45*/, "Windows Server 2008 Datacenter V", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008C },
- { { 0xc1af4d90, 0xd1bc, 0x44ca, { 0x85, 0xd4, 0x00, 0x3b, 0xa3, 0x3d, 0xb3, 0xb9, } } /*c1af4d90-d1bc-44ca-85d4-003ba33db3b9*/, "Windows Server 2008 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008B },
- { { 0x8198490a, 0xadd0, 0x47b2, { 0xb3, 0xba, 0x31, 0x6b, 0x12, 0xd6, 0x47, 0xb4, } } /*8198490a-add0-47b2-b3ba-316b12d647b4*/, "Windows Server 2008 Enterprise V", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008B },
- { { 0xddfa9f7c, 0xf09e, 0x40b9, { 0x8c, 0x1a, 0xbe, 0x87, 0x7a, 0x9a, 0x7f, 0x4b, } } /*ddfa9f7c-f09e-40b9-8c1a-be877a9a7f4b*/, "Windows Server 2008 Web", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008A },
- { { 0x7afb1156, 0x2c1d, 0x40fc, { 0xb2, 0x60, 0xaa, 0xb7, 0x44, 0x2b, 0x62, 0xfe, } } /*7afb1156-2c1d-40fc-b260-aab7442b62fe*/, "Windows Server 2008 Compute Cluster", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008C },
- { { 0x68531fb9, 0x5511, 0x4989, { 0x97, 0xbe, 0xd1, 0x1a, 0x0f, 0x55, 0x63, 0x3f, } } /*68531fb9-5511-4989-97be-d11a0f55633f*/, "Windows Server 2008 R2 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2A },
- { { 0x7482e61b, 0xc589, 0x4b7f, { 0x8e, 0xcc, 0x46, 0xd4, 0x55, 0xac, 0x3b, 0x87, } } /*7482e61b-c589-4b7f-8ecc-46d455ac3b87*/, "Windows Server 2008 R2 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2C },
- { { 0x620e2b3d, 0x09e7, 0x42fd, { 0x80, 0x2a, 0x17, 0xa1, 0x36, 0x52, 0xfe, 0x7a, } } /*620e2b3d-09e7-42fd-802a-17a13652fe7a*/, "Windows Server 2008 R2 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2B },
- { { 0xa78b8bd9, 0x8017, 0x4df5, { 0xb8, 0x6a, 0x09, 0xf7, 0x56, 0xaf, 0xfa, 0x7c, } } /*a78b8bd9-8017-4df5-b86a-09f756affa7c*/, "Windows Server 2008 R2 Web", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2A },
- { { 0xcda18cf3, 0xc196, 0x46ad, { 0xb2, 0x89, 0x60, 0xc0, 0x72, 0x86, 0x99, 0x94, } } /*cda18cf3-c196-46ad-b289-60c072869994*/, "Windows Server 2008 R2 Compute Cluster", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2C },
- { { 0xd3643d60, 0x0c42, 0x412d, { 0xa7, 0xd6, 0x52, 0xe6, 0x63, 0x53, 0x27, 0xf6, } } /*d3643d60-0c42-412d-a7d6-52e6635327f6*/, "Windows Server 2012 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0xf0f5ec41, 0x0d55, 0x4732, { 0xaf, 0x02, 0x44, 0x0a, 0x44, 0xa3, 0xcf, 0x0f, } } /*f0f5ec41-0d55-4732-af02-440a44a3cf0f*/, "Windows Server 2012 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0x95fd1c83, 0x7df5, 0x494a, { 0xbe, 0x8b, 0x13, 0x00, 0xe1, 0xc9, 0xd1, 0xcd, } } /*95fd1c83-7df5-494a-be8b-1300e1c9d1cd*/, "Windows Server 2012 MultiPoint Premium", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0x7d5486c7, 0xe120, 0x4771, { 0xb7, 0xf1, 0x7b, 0x56, 0xc6, 0xd3, 0x17, 0x0c, } } /*7d5486c7-e120-4771-b7f1-7b56c6d3170c*/, "Windows Server 2012 MultiPoint Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0x00091344, 0x1ea4, 0x4f37, { 0xb7, 0x89, 0x01, 0x75, 0x0b, 0xa6, 0x98, 0x8c, } } /*00091344-1ea4-4f37-b789-01750ba6988c*/, "Windows Server 2012 R2 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0xb3ca044e, 0xa358, 0x4d68, { 0x98, 0x83, 0xaa, 0xa2, 0x94, 0x1a, 0xca, 0x99, } } /*b3ca044e-a358-4d68-9883-aaa2941aca99*/, "Windows Server 2012 R2 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0xb743a2be, 0x68d4, 0x4dd3, { 0xaf, 0x32, 0x92, 0x42, 0x5b, 0x7b, 0xb6, 0x23, } } /*b743a2be-68d4-4dd3-af32-92425b7bb623*/, "Windows Server 2012 R2 Cloud Storage", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0x21db6ba4, 0x9a7b, 0x4a14, { 0x9e, 0x29, 0x64, 0xa6, 0x0c, 0x59, 0x30, 0x1d, } } /*21db6ba4-9a7b-4a14-9e29-64a60c59301d*/, "Windows Server 2012 R2 Essentials", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0xba947c44, 0xd19d, 0x4786, { 0xb6, 0xae, 0x22, 0x77, 0x0b, 0xc9, 0x4c, 0x54, } } /*ba947c44-d19d-4786-b6ae-22770bc94c54*/, "Windows Server 2016 Datacenter Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_SRV_BETA },
-
-
- // Windows 10 Preview
-# ifdef INCLUDE_BETAS
- { { 0x6496e59d, 0x89dc, 0x49eb, { 0xa3, 0x53, 0x09, 0xce, 0xb9, 0x40, 0x48, 0x45, } } /*6496e59d-89dc-49eb-a353-09ceb9404845*/, "Windows 10 Core Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0xa4383e6b, 0xdada, 0x423d, { 0xa4, 0x3d, 0xf2, 0x56, 0x78, 0x42, 0x96, 0x76, } } /*a4383e6b-dada-423d-a43d-f25678429676*/, "Windows 10 Professional Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0xcf59a07b, 0x1a2a, 0x4be0, { 0xbf, 0xe0, 0x42, 0x3b, 0x58, 0x23, 0xe6, 0x63, } } /*cf59a07b-1a2a-4be0-bfe0-423b5823e663*/, "Windows 10 Professional WMC Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0xcde952c7, 0x2f96, 0x4d9d, { 0x8f, 0x2b, 0x2d, 0x34, 0x9f, 0x64, 0xfc, 0x51, } } /*cde952c7-2f96-4d9d-8f2b-2d349f64fc51*/, "Windows 10 Enterprise Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
-# endif
-
-
- // Windows 10
-
- { { 0x73111121, 0x5638, 0x40f6, { 0xbc, 0x11, 0xf1, 0xd7, 0xb0, 0xd6, 0x43, 0x00, } } /*73111121-5638-40f6-bc11-f1d7b0d64300*/, "Windows 10 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL },
- { { 0xe272e3e2, 0x732f, 0x4c65, { 0xa8, 0xf0, 0x48, 0x47, 0x47, 0xd0, 0xd9, 0x47, } } /*e272e3e2-732f-4c65-a8f0-484747d0d947*/, "Windows 10 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x7b51a46c, 0x0c04, 0x4e8f, { 0x9a, 0xf4, 0x84, 0x96, 0xcc, 0xa9, 0x0d, 0x5e, } } /*7b51a46c-0c04-4e8f-9af4-8496cca90d5e*/, "Windows 10 Enterprise LTSB", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x87b838b7, 0x41b6, 0x4590, { 0x83, 0x18, 0x57, 0x97, 0x95, 0x1d, 0x85, 0x29, } } /*87b838b7-41b6-4590-8318-5797951d8529*/, "Windows 10 Enterprise LTSB N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0xe0c42288, 0x980c, 0x4788, { 0xa0, 0x14, 0xc0, 0x80, 0xd2, 0xe1, 0x92, 0x6e, } } /*e0c42288-980c-4788-a014-c080d2e1926e*/, "Windows 10 Education", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x3c102355, 0xd027, 0x42c6, { 0xad, 0x23, 0x2e, 0x7e, 0xf8, 0xa0, 0x25, 0x85, } } /*3c102355-d027-42c6-ad23-2e7ef8a02585*/, "Windows 10 Education N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x2de67392, 0xb7a7, 0x462a, { 0xb1, 0xca, 0x10, 0x8d, 0xd1, 0x89, 0xf5, 0x88, } } /*2de67392-b7a7-462a-b1ca-108dd189f588*/, "Windows 10 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL },
- { { 0xa80b5abf, 0x75ad, 0x428b, { 0xb0, 0x5d, 0xa4, 0x7d, 0x2d, 0xff, 0xee, 0xbf, } } /*a80b5abf-76ad-428b-b05d-a47d2dffeebf*/, "Windows 10 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x58e97c99, 0xf377, 0x4ef1, { 0x81, 0xd5, 0x4a, 0xd5, 0x52, 0x2b, 0x5f, 0xd8, } } /*58e97c99-f377-4ef1-81d5-4ad5522b5fd8*/, "Windows 10 Home", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
- { { 0x7b9e1751, 0xa8da, 0x4f75, { 0x95, 0x60, 0x5f, 0xad, 0xfe, 0x3d, 0x8e, 0x38, } } /*7b9e1751-a8da-4f75-9560-5fadfe3d8e38*/, "Windows 10 Home N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
- { { 0xcd918a57, 0xa41b, 0x4c82, { 0x8d, 0xce, 0x1a, 0x53, 0x8e, 0x22, 0x1a, 0x83, } } /*cd918a57-a41b-4c82-8dce-1a538e221a83*/, "Windows 10 Home Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
- { { 0xa9107544, 0xf4a0, 0x4053, { 0xa9, 0x6a, 0x14, 0x79, 0xab, 0xde, 0xf9, 0x12, } } /*a9107544-f4a0-4053-a96a-1479abdef912*/, "Windows 10 Home Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
-
-
- // Windows 8.x
-
-# ifdef INCLUDE_BETAS
- { { 0x2B9C337F, 0x7A1D, 0x4271, { 0x90, 0xA3, 0xC6, 0x85, 0x5A, 0x2B, 0x8A, 0x1C, } } /*2B9C337F-7A1D-4271-90A3-C6855A2B8A1C*/, "Windows 8.x Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0x631EAD72, 0xA8AB, 0x4DF8, { 0xBB, 0xDF, 0x37, 0x20, 0x29, 0x98, 0x9B, 0xDD, } } /*631EAD72-A8AB-4DF8-BBDF-372029989BDD*/, "Windows 8.x Preview ARM", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
-# endif
- { { 0x81671aaf, 0x79d1, 0x4eb1, { 0xb0, 0x04, 0x8c, 0xbb, 0xe1, 0x73, 0xaf, 0xea, } } /*81671aaf-79d1-4eb1-b004-8cbbe173afea*/, "Windows 8.1 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0x113e705c, 0xfa49, 0x48a4, { 0xbe, 0xea, 0x7d, 0xd8, 0x79, 0xb4, 0x6b, 0x14, } } /*113e705c-fa49-48a4-beea-7dd879b46b14*/, "Windows 8.1 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0x096ce63d, 0x4fac, 0x48a9, { 0x82, 0xa9, 0x61, 0xae, 0x9e, 0x80, 0x0e, 0x5f, } } /*096ce63d-4fac-48a9-82a9-61ae9e800e5f*/, "Windows 8.1 Professional WMC", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xc06b6981, 0xd7fd, 0x4a35, { 0xb7, 0xb4, 0x05, 0x47, 0x42, 0xb7, 0xaf, 0x67, } } /*c06b6981-d7fd-4a35-b7b4-054742b7af67*/, "Windows 8.1 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0x7476d79f, 0x8e48, 0x49b4, { 0xab, 0x63, 0x4d, 0x0b, 0x81, 0x3a, 0x16, 0xe4, } } /*7476d79f-8e48-49b4-ab63-4d0b813a16e4*/, "Windows 8.1 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xfe1c3238, 0x432a, 0x43a1, { 0x8e, 0x25, 0x97, 0xe7, 0xd1, 0xef, 0x10, 0xf3, } } /*fe1c3238-432a-43a1-8e25-97e7d1ef10f3*/, "Windows 8.1 Core", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0x78558a64, 0xdc19, 0x43fe, { 0xa0, 0xd0, 0x80, 0x75, 0xb2, 0xa3, 0x70, 0xa3, } } /*78558a64-dc19-43fe-a0d0-8075b2a370a3*/, "Windows 8.1 Core N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xffee456a, 0xcd87, 0x4390, { 0x8e, 0x07, 0x16, 0x14, 0x6c, 0x67, 0x2f, 0xd0, } } /*ffee456a-cd87-4390-8e07-16146c672fd0*/, "Windows 8.1 Core ARM", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xc72c6a1d, 0xf252, 0x4e7e, { 0xbd, 0xd1, 0x3f, 0xca, 0x34, 0x2a, 0xcb, 0x35, } } /*c72c6a1d-f252-4e7e-bdd1-3fca342acb35*/, "Windows 8.1 Core Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xdb78b74f, 0xef1c, 0x4892, { 0xab, 0xfe, 0x1e, 0x66, 0xb8, 0x23, 0x1d, 0xf6, } } /*db78b74f-ef1c-4892-abfe-1e66b8231df6*/, "Windows 8.1 Core Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xe9942b32, 0x2e55, 0x4197, { 0xb0, 0xbd, 0x5f, 0xf5, 0x8c, 0xba, 0x88, 0x60, } } /*e9942b32-2e55-4197-b0bd-5ff58cba8860*/, "Windows 8.1 Core Connected", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xc6ddecd6, 0x2354, 0x4c19, { 0x90, 0x9b, 0x30, 0x6a, 0x30, 0x58, 0x48, 0x4e, } } /*c6ddecd6-2354-4c19-909b-306a3058484e*/, "Windows 8.1 Core Connected N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xb8f5e3a3, 0xed33, 0x4608, { 0x81, 0xe1, 0x37, 0xd6, 0xc9, 0xdc, 0xfd, 0x9c, } } /*b8f5e3a3-ed33-4608-81e1-37d6c9dcfd9c*/, "Windows 8.1 Core Connected Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xba998212, 0x460a, 0x44db, { 0xbf, 0xb5, 0x71, 0xbf, 0x09, 0xd1, 0xc6, 0x8b, } } /*ba998212-460a-44db-bfb5-71bf09d1c68b*/, "Windows 8.1 Core Connected Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xe58d87b5, 0x8126, 0x4580, { 0x80, 0xfb, 0x86, 0x1b, 0x22, 0xf7, 0x92, 0x96, } } /*e58d87b5-8126-4580-80fb-861b22f79296*/, "Windows 8.1 Professional Student", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xcab491c7, 0xa918, 0x4f60, { 0xb5, 0x02, 0xda, 0xb7, 0x5e, 0x33, 0x4f, 0x40, } } /*cab491c7-a918-4f60-b502-dab75e334f40*/, "Windows 8.1 Professional Student N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xa00018a3, 0xf20f, 0x4632, { 0xbf, 0x7c, 0x8d, 0xaa, 0x53, 0x51, 0xc9, 0x14, } } /*a00018a3-f20f-4632-bf7c-8daa5351c914*/, "Windows 8 Professional WMC", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0xa98bcd6d, 0x5343, 0x4603, { 0x8a, 0xfe, 0x59, 0x08, 0xe4, 0x61, 0x11, 0x12, } } /*a98bcd6d-5343-4603-8afe-5908e4611112*/, "Windows 8 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0xebf245c1, 0x29a8, 0x4daf, { 0x9c, 0xb1, 0x38, 0xdf, 0xc6, 0x08, 0xa8, 0xc8, } } /*ebf245c1-29a8-4daf-9cb1-38dfc608a8c8*/, "Windows 8 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0x458e1bec, 0x837a, 0x45f6, { 0xb9, 0xd5, 0x92, 0x5e, 0xd5, 0xd2, 0x99, 0xde, } } /*458e1bec-837a-45f6-b9d5-925ed5d299de*/, "Windows 8 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0xe14997e7, 0x800a, 0x4cf7, { 0xad, 0x10, 0xde, 0x4b, 0x45, 0xb5, 0x78, 0xdb, } } /*e14997e7-800a-4cf7-ad10-de4b45b578db*/, "Windows 8 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0xc04ed6bf, 0x55c8, 0x4b47, { 0x9f, 0x8e, 0x5a, 0x1f, 0x31, 0xce, 0xee, 0x60, } } /*c04ed6bf-55c8-4b47-9f8e-5a1f31ceee60*/, "Windows 8 Core", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0x197390a0, 0x65f6, 0x4a95, { 0xbd, 0xc4, 0x55, 0xd5, 0x8a, 0x3b, 0x02, 0x53, } } /*197390a0-65f6-4a95-bdc4-55d58a3b0253*/, "Windows 8 Core N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0x9d5584a2, 0x2d85, 0x419a, { 0x98, 0x2c, 0xa0, 0x08, 0x88, 0xbb, 0x9d, 0xdf, } } /*9d5584a2-2d85-419a-982c-a00888bb9ddf*/, "Windows 8 Core Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0x8860fcd4, 0xa77b, 0x4a20, { 0x90, 0x45, 0xa1, 0x50, 0xff, 0x11, 0xd6, 0x09, } } /*8860fcd4-a77b-4a20-9045-a150ff11d609*/, "Windows 8 Core Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
-
-
- // Windows 7
-
- { { 0xae2ee509, 0x1b34, 0x41c0, { 0xac, 0xb7, 0x6d, 0x46, 0x50, 0x16, 0x89, 0x15, } } /*ae2ee509-1b34-41c0-acb7-6d4650168915*/, "Windows 7 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0x1cb6d605, 0x11b3, 0x4e14, { 0xbb, 0x30, 0xda, 0x91, 0xc8, 0xe3, 0x98, 0x3a, } } /*1cb6d605-11b3-4e14-bb30-da91c8e3983a*/, "Windows 7 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0xb92e9980, 0xb9d5, 0x4821, { 0x9c, 0x94, 0x14, 0x0f, 0x63, 0x2f, 0x63, 0x12, } } /*b92e9980-b9d5-4821-9c94-140f632f6312*/, "Windows 7 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0x54a09a0d, 0xd57b, 0x4c10, { 0x8b, 0x69, 0xa8, 0x42, 0xd6, 0x59, 0x0a, 0xd5, } } /*54a09a0d-d57b-4c10-8b69-a842d6590ad5*/, "Windows 7 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
-
-
- // Windows Vista
-
- { { 0xcfd8ff08, 0xc0d7, 0x452b, { 0x9f, 0x60, 0xef, 0x5c, 0x70, 0xc3, 0x20, 0x94, } } /*cfd8ff08-c0d7-452b-9f60-ef5c70c32094*/, "Windows Vista Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
- { { 0xd4f54950, 0x26f2, 0x4fb4, { 0xba, 0x21, 0xff, 0xab, 0x16, 0xaf, 0xca, 0xde, } } /*d4f54950-26f2-4fb4-ba21-ffab16afcade*/, "Windows Vista Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
- { { 0x4f3d1606, 0x3fea, 0x4c01, { 0xbe, 0x3c, 0x8d, 0x67, 0x1c, 0x40, 0x1e, 0x3b, } } /*4f3d1606-3fea-4c01-be3c-8d671c401e3b*/, "Windows Vista Business", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
- { { 0x2c682dc2, 0x8b68, 0x4f63, { 0xa1, 0x65, 0xae, 0x29, 0x1d, 0x4c, 0xf1, 0x38, } } /*2c682dc2-8b68-4f63-a165-ae291d4cf138*/, "Windows Vista Business N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
-
-
- // Windows Embedded
-
- { { 0xaa6dd3aa, 0xc2b4, 0x40e2, { 0xa5, 0x44, 0xa6, 0xbb, 0xb3, 0xf5, 0xc3, 0x95, } } /*aa6dd3aa-c2b4-40e2-a544-a6bbb3f5c395*/, "Windows ThinPC", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0xdb537896, 0x376f, 0x48ae, { 0xa4, 0x92, 0x53, 0xd0, 0x54, 0x77, 0x73, 0xd0, } } /*db537896-376f-48ae-a492-53d0547773d0*/, "Windows Embedded POSReady 7", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0x0ab82d54, 0x47f4, 0x4acb, { 0x81, 0x8c, 0xcc, 0x5b, 0xf0, 0xec, 0xb6, 0x49, } } /*0ab82d54-47f4-4acb-818c-cc5bf0ecb649*/, "Windows Embedded Industry 8.1", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xcd4e2d9f, 0x5059, 0x4a50, { 0xa9, 0x2d, 0x05, 0xd5, 0xbb, 0x12, 0x67, 0xc7, } } /*cd4e2d9f-5059-4a50-a92d-05d5bb1267c7*/, "Windows Embedded Industry E 8.1", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xf7e88590, 0xdfc7, 0x4c78, { 0xbc, 0xcb, 0x6f, 0x38, 0x65, 0xb9, 0x9d, 0x1a, } } /*f7e88590-dfc7-4c78-bccb-6f3865b99d1a*/, "Windows Embedded Industry A 8.1", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
-
- // Office 2010
-
- { { 0x8ce7e872, 0x188c, 0x4b98, { 0x9d, 0x90, 0xf8, 0xf9, 0x0b, 0x7a, 0xad, 0x02, } } /*8ce7e872-188c-4b98-9d90-f8f90b7aad02*/, "Office Access 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xcee5d470, 0x6e3b, 0x4fcc, { 0x8c, 0x2b, 0xd1, 0x74, 0x28, 0x56, 0x8a, 0x9f, } } /*cee5d470-6e3b-4fcc-8c2b-d17428568a9f*/, "Office Excel 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x8947d0b8, 0xc33b, 0x43e1, { 0x8c, 0x56, 0x9b, 0x67, 0x4c, 0x05, 0x28, 0x32, } } /*8947d0b8-c33b-43e1-8c56-9b674c052832*/, "Office Groove 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xca6b6639, 0x4ad6, 0x40ae, { 0xa5, 0x75, 0x14, 0xde, 0xe0, 0x7f, 0x64, 0x30, } } /*ca6b6639-4ad6-40ae-a575-14dee07f6430*/, "Office InfoPath 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x09ed9640, 0xf020, 0x400a, { 0xac, 0xd8, 0xd7, 0xd8, 0x67, 0xdf, 0xd9, 0xc2, } } /*09ed9640-f020-400a-acd8-d7d867dfd9c2*/, "Office Mondo 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xef3d4e49, 0xa53d, 0x4d81, { 0xa2, 0xb1, 0x2c, 0xa6, 0xc2, 0x55, 0x6b, 0x2c, } } /*ef3d4e49-a53d-4d81-a2b1-2ca6c2556b2c*/, "Office Mondo 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xab586f5c, 0x5256, 0x4632, { 0x96, 0x2f, 0xfe, 0xfd, 0x8b, 0x49, 0xe6, 0xf4, } } /*ab586f5c-5256-4632-962f-fefd8b49e6f4*/, "Office OneNote 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xecb7c192, 0x73ab, 0x4ded, { 0xac, 0xf4, 0x23, 0x99, 0xb0, 0x95, 0xd0, 0xcc, } } /*ecb7c192-73ab-4ded-acf4-2399b095d0cc*/, "Office OutLook 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x45593b1d, 0xdfb1, 0x4e91, { 0xbb, 0xfb, 0x2d, 0x5d, 0x0c, 0xe2, 0x22, 0x7a, } } /*45593b1d-dfb1-4e91-bbfb-2d5d0ce2227a*/, "Office PowerPoint 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xdf133ff7, 0xbf14, 0x4f95, { 0xaf, 0xe3, 0x7b, 0x48, 0xe7, 0xe3, 0x31, 0xef, } } /*df133ff7-bf14-4f95-afe3-7b48e7e331ef*/, "Office Project Pro 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x5dc7bf61, 0x5ec9, 0x4996, { 0x9c, 0xcb, 0xdf, 0x80, 0x6a, 0x2d, 0x0e, 0xfe, } } /*5dc7bf61-5ec9-4996-9ccb-df806a2d0efe*/, "Office Project Standard 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xb50c4f75, 0x599b, 0x43e8, { 0x8d, 0xcd, 0x10, 0x81, 0xa7, 0x96, 0x72, 0x41, } } /*b50c4f75-599b-43e8-8dcd-1081a7967241*/, "Office Publisher 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x92236105, 0xbb67, 0x494f, { 0x94, 0xc7, 0x7f, 0x7a, 0x60, 0x79, 0x29, 0xbd, } } /*92236105-bb67-494f-94c7-7f7a607929bd*/, "Office Visio Premium 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xe558389c, 0x83c3, 0x4b29, { 0xad, 0xfe, 0x5e, 0x4d, 0x7f, 0x46, 0xc3, 0x58, } } /*e558389c-83c3-4b29-adfe-5e4d7f46c358*/, "Office Visio Pro 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x9ed833ff, 0x4f92, 0x4f36, { 0xb3, 0x70, 0x86, 0x83, 0xa4, 0xf1, 0x32, 0x75, } } /*9ed833ff-4f92-4f36-b370-8683a4f13275*/, "Office Visio Standard 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x2d0882e7, 0xa4e7, 0x423b, { 0x8c, 0xcc, 0x70, 0xd9, 0x1e, 0x01, 0x58, 0xb1, } } /*2d0882e7-a4e7-423b-8ccc-70d91e0158b1*/, "Office Word 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x6f327760, 0x8c5c, 0x417c, { 0x9b, 0x61, 0x83, 0x6a, 0x98, 0x28, 0x7e, 0x0c, } } /*6f327760-8c5c-417c-9b61-836a98287e0c*/, "Office Professional Plus 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x9da2a678, 0xfb6b, 0x4e67, { 0xab, 0x84, 0x60, 0xdd, 0x6a, 0x9c, 0x81, 0x9a, } } /*9da2a678-fb6b-4e67-ab84-60dd6a9c819a*/, "Office Standard 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xea509e87, 0x07a1, 0x4a45, { 0x9e, 0xdc, 0xeb, 0xa5, 0xa3, 0x9f, 0x36, 0xaf, } } /*ea509e87-07a1-4a45-9edc-eba5a39f36af*/, "Office Small Business Basics 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
-
- // Office 2013
-
- { { 0x6ee7622c, 0x18d8, 0x4005, { 0x9f, 0xb7, 0x92, 0xdb, 0x64, 0x4a, 0x27, 0x9b, } } /*6ee7622c-18d8-4005-9fb7-92db644a279b*/, "Office Access 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xf7461d52, 0x7c2b, 0x43b2, { 0x87, 0x44, 0xea, 0x95, 0x8e, 0x0b, 0xd0, 0x9a, } } /*f7461d52-7c2b-43b2-8744-ea958e0bd09a*/, "Office Excel 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xa30b8040, 0xd68a, 0x423f, { 0xb0, 0xb5, 0x9c, 0xe2, 0x92, 0xea, 0x5a, 0x8f, } } /*a30b8040-d68a-423f-b0b5-9ce292ea5a8f*/, "Office InfoPath 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x1b9f11e3, 0xc85c, 0x4e1b, { 0xbb, 0x29, 0x87, 0x9a, 0xd2, 0xc9, 0x09, 0xe3, } } /*1b9f11e3-c85c-4e1b-bb29-879ad2c909e3*/, "Office Lync 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xdc981c6b, 0xfc8e, 0x420f, { 0xaa, 0x43, 0xf8, 0xf3, 0x3e, 0x5c, 0x09, 0x23, } } /*dc981c6b-fc8e-420f-aa43-f8f33e5c0923*/, "Office Mondo 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xefe1f3e6, 0xaea2, 0x4144, { 0xa2, 0x08, 0x32, 0xaa, 0x87, 0x2b, 0x65, 0x45, } } /*efe1f3e6-aea2-4144-a208-32aa872b6545*/, "Office OneNote 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x771c3afa, 0x50c5, 0x443f, { 0xb1, 0x51, 0xff, 0x25, 0x46, 0xd8, 0x63, 0xa0, } } /*771c3afa-50c5-443f-b151-ff2546d863a0*/, "Office OutLook 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x8c762649, 0x97d1, 0x4953, { 0xad, 0x27, 0xb7, 0xe2, 0xc2, 0x5b, 0x97, 0x2e, } } /*8c762649-97d1-4953-ad27-b7e2c25b972e*/, "Office PowerPoint 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x4a5d124a, 0xe620, 0x44ba, { 0xb6, 0xff, 0x65, 0x89, 0x61, 0xb3, 0x3b, 0x9a, } } /*4a5d124a-e620-44ba-b6ff-658961b33b9a*/, "Office Project Pro 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x427a28d1, 0xd17c, 0x4abf, { 0xb7, 0x17, 0x32, 0xc7, 0x80, 0xba, 0x6f, 0x07, } } /*427a28d1-d17c-4abf-b717-32c780ba6f07*/, "Office Project Standard 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x00c79ff1, 0x6850, 0x443d, { 0xbf, 0x61, 0x71, 0xcd, 0xe0, 0xde, 0x30, 0x5f, } } /*00c79ff1-6850-443d-bf61-71cde0de305f*/, "Office Publisher 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xac4efaf0, 0xf81f, 0x4f61, { 0xbd, 0xf7, 0xea, 0x32, 0xb0, 0x2a, 0xb1, 0x17, } } /*ac4efaf0-f81f-4f61-bdf7-ea32b02ab117*/, "Office Visio Standard 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xe13ac10e, 0x75d0, 0x4aff, { 0xa0, 0xcd, 0x76, 0x49, 0x82, 0xcf, 0x54, 0x1c, } } /*e13ac10e-75d0-4aff-a0cd-764982cf541c*/, "Office Visio Pro 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xd9f5b1c6, 0x5386, 0x495a, { 0x88, 0xf9, 0x9a, 0xd6, 0xb4, 0x1a, 0xc9, 0xb3, } } /*d9f5b1c6-5386-495a-88f9-9ad6b41ac9b3*/, "Office Word 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xb322da9c, 0xa2e2, 0x4058, { 0x9e, 0x4e, 0xf5, 0x9a, 0x69, 0x70, 0xbd, 0x69, } } /*b322da9c-a2e2-4058-9e4e-f59a6970bd69*/, "Office Professional Plus 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xb13afb38, 0xcd79, 0x4ae5, { 0x9f, 0x7f, 0xee, 0xd0, 0x58, 0xd7, 0x50, 0xca, } } /*b13afb38-cd79-4ae5-9f7f-eed058d750ca*/, "Office Standard 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
-
- // Office 2016
-
- { { 0xd450596f, 0x894d, 0x49e0, { 0x96, 0x6a, 0xfd, 0x39, 0xed, 0x4c, 0x4c, 0x64, } } /*d450596f-894d-49e0-966a-fd39ed4c4c64*/, "Office Professional Plus 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x4f414197, 0x0fc2, 0x4c01, { 0xb6, 0x8a, 0x86, 0xcb, 0xb9, 0xac, 0x25, 0x4c, } } /*4f414197-0fc2-4c01-b68a-86cbb9ac254c*/, "Office Project Pro 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x6bf301c1, 0xb94a, 0x43e9, { 0xba, 0x31, 0xd4, 0x94, 0x59, 0x8c, 0x47, 0xfb, } } /*6bf301c1-b94a-43e9-ba31-d494598c47fb*/, "Office Visio Pro 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x041a06cb, 0xc5b8, 0x4772, { 0x80, 0x9f, 0x41, 0x6d, 0x03, 0xd1, 0x66, 0x54, } } /*041a06cb-c5b8-4772-809f-416d03d16654*/, "Office Publisher 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x67c0fc0c, 0xdeba, 0x401b, { 0xbf, 0x8b, 0x9c, 0x8a, 0xd8, 0x39, 0x58, 0x04, } } /*67c0fc0c-deba-401b-bf8b-9c8ad8395804*/, "Office Access 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x83e04ee1, 0xfa8d, 0x436d, { 0x89, 0x94, 0xd3, 0x1a, 0x86, 0x2c, 0xab, 0x77, } } /*83e04ee1-fa8d-436d-8994-d31a862cab77*/, "Office Skype for Business 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x9caabccb, 0x61b1, 0x4b4b, { 0x8b, 0xec, 0xd1, 0x0a, 0x3c, 0x3a, 0xc2, 0xce, } } /*9caabccb-61b1-4b4b-8bec-d10a3c3ac2ce*/, "Office Mondo 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xaa2a7821, 0x1827, 0x4c2c, { 0x8f, 0x1d, 0x45, 0x13, 0xa3, 0x4d, 0xda, 0x97, } } /*aa2a7821-1827-4c2c-8f1d-4513a34dda97*/, "Office Visio Standard 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xbb11badf, 0xd8aa, 0x470e, { 0x93, 0x11, 0x20, 0xea, 0xf8, 0x0f, 0xe5, 0xcc, } } /*bb11badf-d8aa-470e-9311-20eaf80fe5cc*/, "Office Word 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xc3e65d36, 0x141f, 0x4d2f, { 0xa3, 0x03, 0xa8, 0x42, 0xee, 0x75, 0x6a, 0x29, } } /*c3e65d36-141f-4d2f-a303-a842ee756a29*/, "Office Excel 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xd70b1bba, 0xb893, 0x4544, { 0x96, 0xe2, 0xb7, 0xa3, 0x18, 0x09, 0x1c, 0x33, } } /*d70b1bba-b893-4544-96e2-b7a318091c33*/, "Office Powerpoint 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xd8cace59, 0x33d2, 0x4ac7, { 0x9b, 0x1b, 0x9b, 0x72, 0x33, 0x9c, 0x51, 0xc8, } } /*d8cace59-33d2-4ac7-9b1b-9b72339c51c8*/, "Office OneNote 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xda7ddabc, 0x3fbe, 0x4447, { 0x9e, 0x01, 0x6a, 0xb7, 0x44, 0x0b, 0x4c, 0xd4, } } /*da7ddabc-3fbe-4447-9e01-6ab7440b4cd4*/, "Office Project Standard 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xdedfa23d, 0x6ed1, 0x45a6, { 0x85, 0xdc, 0x63, 0xca, 0xe0, 0x54, 0x6d, 0xe6, } } /*dedfa23d-6ed1-45a6-85dc-63cae0546de6*/, "Office Standard 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xe914ea6e, 0xa5fa, 0x4439, { 0xa3, 0x94, 0xa9, 0xbb, 0x32, 0x93, 0xca, 0x09, } } /*e914ea6e-a5fa-4439-a394-a9bb3293ca09*/, "Office Mondo R 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xec9d9265, 0x9d1e, 0x4ed0, { 0x83, 0x8a, 0xcd, 0xc2, 0x0f, 0x25, 0x51, 0xa1, } } /*ec9d9265-9d1e-4ed0-838a-cdc20f2551a1*/, "Office Outlook 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
-
- // End marker (necessity should be removed when time permits)
-
- { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
-};
-
-
-// necessary because other .c files cannot access _countof()
-__pure ProdListIndex_t getExtendedProductListSize(void)
-{
- return _countof(ExtendedProductList) - 1;
-}
-
-__pure ProdListIndex_t getAppListSize(void)
-{
- return _countof(AppList);
-}
-
-#endif
-
-#ifndef NO_RANDOM_EPID
-// HostType and OSBuild
-static const struct KMSHostOS { uint16_t Type; uint16_t Build; } HostOS[] =
-{
- { 55041, 6002 }, // Windows Server 2008 SP2
- { 55041, 7601 }, // Windows Server 2008 R2 SP1
- { 5426, 9200 }, // Windows Server 2012
- { 6401, 9600 }, // Windows Server 2012 R2
- { 3612, 10240}, // Windows Server 2016
-};
-
-// GroupID and PIDRange
-static const struct PKEYCONFIG { uint16_t GroupID; uint32_t RangeMin; uint32_t RangeMax; } pkeyconfig[] = {
- { 206, 152000000, 191999999 }, // Windows Server 2012 KMS Host pkeyconfig
- { 206, 271000000, 310999999 }, // Windows Server 2012 R2 KMS Host pkeyconfig
- { 96, 199000000, 217999999 }, // Office2010 KMS Host pkeyconfig
- { 206, 234000000, 255999999 }, // Office2013 KMS Host pkeyconfig
-};
-
-// Valid language identifiers to be used in the ePID
-static const uint16_t LcidList[] = {
- 1078, 1052, 1025, 2049, 3073, 4097, 5121, 6145, 7169, 8193, 9217, 10241, 11265, 12289, 13313, 14337, 15361, 16385,
- 1067, 1068, 2092, 1069, 1059, 1093, 5146, 1026, 1027, 1028, 2052, 3076, 4100, 5124, 1050, 4122, 1029, 1030, 1125, 1043, 2067,
- 1033, 2057, 3081, 4105, 5129, 6153, 7177, 8201, 9225, 10249, 11273, 12297, 13321, 1061, 1080, 1065, 1035, 1036, 2060,
- 3084, 4108, 5132, 6156, 1079, 1110, 1031, 2055, 3079, 4103, 5127, 1032, 1095, 1037, 1081, 1038, 1039, 1057, 1040, 2064, 1041, 1099,
- 1087, 1111, 1042, 1088, 1062, 1063, 1071, 1086, 2110, 1100, 1082, 1153, 1102, 1104, 1044, 2068, 1045, 1046, 2070,
- 1094, 1131, 2155, 3179, 1048, 1049, 9275, 4155, 5179, 3131, 1083, 2107, 8251, 6203, 7227, 1103, 2074, 6170, 3098,
- 7194, 1051, 1060, 1034, 2058, 3082, 4106, 5130, 6154, 7178, 8202, 9226, 10250, 11274, 12298, 13322, 14346, 15370, 16394,
- 17418, 18442, 19466, 20490, 1089, 1053, 2077, 1114, 1097, 1092, 1098, 1054, 1074, 1058, 1056, 1091, 2115, 1066, 1106, 1076, 1077
-};
-
-
-#ifdef _PEDANTIC
-uint16_t IsValidLcid(const uint16_t Lcid)
-{
- uint16_t i;
-
- for (i = 0; i < _countof(LcidList); i++)
- {
- if (Lcid == LcidList[i]) return Lcid;
- }
-
- return 0;
-}
-#endif // _PEDANTIC
-#endif // NO_RANDOM_EPID
-
-
-// Unix time is seconds from 1970-01-01. Should be 64 bits to avoid Year 2035 overflow bug.
-// FILETIME is 100 nanoseconds from 1601-01-01. Must be 64 bits.
-void getUnixTimeAsFileTime(FILETIME *const ts)
-{
- int64_t unixtime = (int64_t)time(NULL);
- int64_t *filetime = (int64_t*)ts;
-
- *filetime = LE64( (unixtime + 11644473600LL) * 10000000LL );
-}
-
-__pure int64_t fileTimeToUnixTime(const FILETIME *const ts)
-{
- return LE64( *((const int64_t *const)ts) ) / 10000000LL - 11644473600LL;
-}
-
-
-/*
- * Get's a product name with a GUID in host-endian order.
- * List can be any list defined above.
- */
-const char* getProductNameHE(const GUID *const guid, const KmsIdList *const List, ProdListIndex_t *const i)
-{
- for (*i = 0; List[*i].name != NULL; (*i)++)
- {
- if (IsEqualGUID(guid, &List[*i].guid))
- return List[*i].name;
- }
-
- return "Unknown";
-}
-
-
-/*
- * same as getProductnameHE except GUID is in little-endian (network) order
- */
-const char* getProductNameLE(const GUID *const guid, const KmsIdList *const List, ProdListIndex_t *const i)
-{
- #if __BYTE_ORDER != __LITTLE_ENDIAN
- GUID HeGUID;
- LEGUID(&HeGUID, guid);
- return getProductNameHE(&HeGUID, List, i);
- #else
- return getProductNameHE(guid, List, i);
- #endif
-}
-
-
-#ifndef NO_RANDOM_EPID
-// formats an int with a fixed number of digits with leading zeros (helper for ePID generation)
-static char* itoc(char *const c, const int i, uint_fast8_t digits)
-{
- char formatString[8];
- if (digits > 9) digits = 0;
- strcpy(formatString,"%");
-
- if (digits)
- {
- formatString[1] = '0';
- formatString[2] = digits | 0x30;
- formatString[3] = 0;
- }
-
- strcat(formatString, "u");
- sprintf(c, formatString, i);
- return c;
-}
-
-static int getRandomServerType()
-{
-# ifndef USE_MSRPC
- if (!UseRpcBTFN)
-# endif // USE_MSRPC
- {
- // This isn't possible at all, e.g. KMS host on XP
- return rand() % (int)_countof(HostOS);
- }
-# ifndef USE_MSRPC
- else
- {
- // return 9200/9600/10240 if NDR64 is in use, otherwise 6002/7601
- if (UseRpcNDR64) return (rand() % 3) + 2;
- return (rand() % 2);
- }
-# endif // USE_MSRPC
-}
-
-
-/*
- * Generates a random ePID
- */
-static void generateRandomPid(const int index, char *const szPid, int serverType, int16_t lang)
-{
- int clientApp;
- char numberBuffer[12];
-
- if (serverType < 0 || serverType >= (int)_countof(HostOS))
- {
- serverType = getRandomServerType();
- }
-
- strcpy(szPid, itoc(numberBuffer, HostOS[serverType].Type, 5));
- strcat(szPid, "-");
-
- if (index == 2)
- clientApp = 3;
- else if (index == 1)
- clientApp = 2;
- else
- clientApp = serverType == 3 /*change if HostOS changes*/ ? 1 : 0;
-
- strcat(szPid, itoc(numberBuffer, pkeyconfig[clientApp].GroupID, 5));
- strcat(szPid, "-");
-
- int keyId = (rand32() % (pkeyconfig[clientApp].RangeMax - pkeyconfig[clientApp].RangeMin)) + pkeyconfig[clientApp].RangeMin;
- strcat(szPid, itoc(numberBuffer, keyId / 1000000, 3));
- strcat(szPid, "-");
- strcat(szPid, itoc(numberBuffer, keyId % 1000000, 6));
- strcat(szPid, "-03-");
-
- if (lang < 0) lang = LcidList[rand() % _countof(LcidList)];
- strcat(szPid, itoc(numberBuffer, lang, 0));
- strcat(szPid, "-");
-
- strcat(szPid, itoc(numberBuffer, HostOS[serverType].Build, 0));
- strcat(szPid, ".0000-");
-
-# define minTime ((time_t)1436958000) // Release Date Windows 10 RTM Escrow
-
- time_t maxTime, kmsTime;
- time(&maxTime);
-
- if (maxTime < minTime) // Just in case the system time is < 07/15/2015 1:00 pm
- maxTime = (time_t)BUILD_TIME;
-
- kmsTime = (rand32() % (maxTime - minTime)) + minTime;
-# undef minTime
-
- struct tm *pidTime;
- pidTime = gmtime(&kmsTime);
-
- strcat(szPid, itoc(numberBuffer, pidTime->tm_yday, 3));
- strcat(szPid, itoc(numberBuffer, pidTime->tm_year + 1900, 4));
-}
-
-
-/*
- * Generates random ePIDs and stores them if not already read from ini file.
- * For use with randomization level 1
- */
-void randomPidInit()
-{
- ProdListIndex_t i;
-
- int serverType = getRandomServerType();
- int16_t lang = Lcid ? Lcid : LcidList[rand() % _countof(LcidList)];
-
- for (i = 0; i < _countof(AppList) - 1; i++)
- {
- if (KmsResponseParameters[i].Epid) continue;
-
- char Epid[PID_BUFFER_SIZE];
-
- generateRandomPid(i, Epid, serverType, lang);
- KmsResponseParameters[i].Epid = (const char*)vlmcsd_malloc(strlen(Epid) + 1);
-
- strcpy((char*)KmsResponseParameters[i].Epid, Epid);
-
- #ifndef NO_LOG
- KmsResponseParameters[i].EpidSource = "randomized at program start";
- #endif // NO_LOG
- }
-}
-
-#endif // NO_RANDOM_EPID
-
-
-#ifndef NO_LOG
-/*
- * Logs a Request
- */
-static void logRequest(const REQUEST *const baseRequest)
-{
- const char *productName;
- char clientname[64];
- ProdListIndex_t index;
-
- #ifndef NO_EXTENDED_PRODUCT_LIST
- productName = getProductNameLE(&baseRequest->ActID, ExtendedProductList, &index);
- if (++index >= (int)_countof(ExtendedProductList))
- #endif // NO_EXTENDED_PRODUCT_LIST
- {
- #ifndef NO_BASIC_PRODUCT_LIST
- productName = getProductNameLE(&baseRequest->KMSID, ProductList, &index);
- if (++index >= (int)_countof(ProductList))
- #endif // NO_BASIC_PRODUCT_LIST
- {
- productName = getProductNameLE(&baseRequest->AppID, AppList, &index);
- }
- }
-
- #ifndef NO_VERBOSE_LOG
- if (logverbose)
- {
- logger("<<< Incoming KMS request\n");
- logRequestVerbose(baseRequest, &logger);
- }
- else
- {
- #endif // NO_VERBOSE_LOG
- 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);
- #ifndef NO_VERBOSE_LOG
- }
- #endif // NO_VERBOSE_LOG
-}
-#endif // NO_LOG
-
-
-/*
- * Converts a utf-8 ePID string to UCS-2 and writes it to a RESPONSE struct
- */
-static void getEpidFromString(RESPONSE *const Response, const char *const pid)
-{
- size_t length = utf8_to_ucs2(Response->KmsPID, pid, PID_BUFFER_SIZE, PID_BUFFER_SIZE * 3);
- Response->PIDSize = LE32(((unsigned int )length + 1) << 1);
-}
-
-
-/*
- * get ePID from appropriate source
- */
-static void getEpid(RESPONSE *const baseResponse, const char** EpidSource, const ProdListIndex_t index, BYTE *const HwId)
-{
- const char* pid;
- if (KmsResponseParameters[index].Epid == NULL)
- {
- #ifndef NO_RANDOM_EPID
- if (RandomizationLevel == 2)
- {
- char szPid[PID_BUFFER_SIZE];
- generateRandomPid(index, szPid, -1, Lcid ? Lcid : -1);
- pid = szPid;
-
- #ifndef NO_LOG
- *EpidSource = "randomized on every request";
- #endif // NO_LOG
- }
- else
- #endif // NO_RANDOM_EPID
- {
- pid = AppList[index].pid;
- #ifndef NO_LOG
- *EpidSource = "vlmcsd default";
- #endif // NO_LOG
- }
- }
- else
- {
- pid = KmsResponseParameters[index].Epid;
-
- if (HwId && KmsResponseParameters[index].HwId != NULL)
- memcpy(HwId, KmsResponseParameters[index].HwId, sizeof(((RESPONSE_V6 *)0)->HwId));
-
- #ifndef NO_LOG
- *EpidSource = KmsResponseParameters[index].EpidSource;
- #endif // NO_LOG
- }
- getEpidFromString(baseResponse, pid);
-}
-
-
-#if !defined(NO_LOG) && defined(_PEDANTIC)
-static BOOL CheckVersion4Uuid(const GUID *const guid, const char *const szGuidName)
-{
- if (LE16(guid->Data3) >> 12 != 4 || guid->Data4[0] >> 6 != 2)
- {
- logger("Warning: %s does not conform to version 4 UUID according to RFC 4122\n", szGuidName);
- return FALSE;
- }
- return TRUE;
-}
-
-
-static void CheckRequest(const REQUEST *const Request)
-{
- CheckVersion4Uuid(&Request->CMID, "Client machine ID");
- CheckVersion4Uuid(&Request->AppID, "Application ID");
- CheckVersion4Uuid(&Request->KMSID, "Server SKU ID");
- CheckVersion4Uuid(&Request->ActID, "Client SKU ID");
-
- if (LE32(Request->IsClientVM) > 1)
- logger("Warning: Virtual Machine field in request must be 0 or 1 but is %u\n", LE32(Request->IsClientVM));
-
- if (LE32(Request->LicenseStatus) > 6 )
- logger("Warning: License status must be between 0 and 6 but is %u\n", LE32(Request->LicenseStatus));
-}
-#endif // !defined(NO_LOG) && defined(_PEDANTIC)
-
-
-#ifndef NO_LOG
-/*
- * Logs the Response
- */
-static void logResponse(const RESPONSE *const 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);
-
- #ifndef NO_VERBOSE_LOG
- if (!logverbose)
- {
- #endif // NO_VERBOSE_LOG
- logger("Sending ePID (%s): %s\n", EpidSource, utf8pid);
- #ifndef NO_VERBOSE_LOG
- }
- else
- {
- logger(">>> Sending response, ePID source = %s\n", EpidSource);
- logResponseVerbose(utf8pid, hwId, baseResponse, &logger);
- }
- #endif // NO_VERBOSE_LOG
-
-}
-#endif
-
-
-/*
- * Creates the unencrypted base response
- */
-static BOOL __stdcall CreateResponseBaseCallback(const REQUEST *const baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr)
-{
- const char* EpidSource;
- #ifndef NO_LOG
- logRequest(baseRequest);
- #ifdef _PEDANTIC
- CheckRequest(baseRequest);
- #endif // _PEDANTIC
- #endif // NO_LOG
-
- ProdListIndex_t index;
-
- getProductNameLE(&baseRequest->AppID, AppList, &index);
-
- if (index >= _countof(AppList) - 1) index = 0; //default to Windows
-
- getEpid(baseResponse, &EpidSource, index, hwId);
-
- baseResponse->Version = baseRequest->Version;
-
- memcpy(&baseResponse->CMID, &baseRequest->CMID, sizeof(GUID));
- memcpy(&baseResponse->ClientTime, &baseRequest->ClientTime, sizeof(FILETIME));
-
- baseResponse->Count = LE32(LE32(baseRequest->N_Policy) << 1);
- baseResponse->VLActivationInterval = LE32(VLActivationInterval);
- baseResponse->VLRenewalInterval = LE32(VLRenewalInterval);
-
- #ifndef NO_LOG
- logResponse(baseResponse, hwId, EpidSource);
- #endif // NO_LOG
-
- return !0;
-}
-
-RequestCallback_t CreateResponseBase = &CreateResponseBaseCallback;
-
-////TODO: Move to helpers.c
-void get16RandomBytes(void* ptr)
-{
- int i;
- for (i = 0; i < 4; i++) ((DWORD*)ptr)[i] = rand32();
-}
-
-
-/*
- * Creates v4 response
- */
-size_t CreateResponseV4(REQUEST_V4 *const request_v4, BYTE *const responseBuffer, const char* const ipstr)
-{
- RESPONSE_V4* Response = (RESPONSE_V4*)responseBuffer;
-
- if ( !CreateResponseBase(&request_v4->RequestBase, &Response->ResponseBase, NULL, ipstr) ) return 0;
-
- DWORD pidSize = LE32(Response->ResponseBase.PIDSize);
- BYTE* postEpidPtr = responseBuffer + V4_PRE_EPID_SIZE + pidSize;
- memmove(postEpidPtr, &Response->ResponseBase.CMID, V4_POST_EPID_SIZE);
-
- size_t encryptSize = V4_PRE_EPID_SIZE + V4_POST_EPID_SIZE + pidSize;
- AesCmacV4(responseBuffer, encryptSize, responseBuffer + encryptSize);
-
- return encryptSize + sizeof(Response->MAC);
-}
-
-/*
-// Workaround for buggy GCC 4.2/4.3
-#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 4)
-__attribute__((noinline))
-#endif
-__pure static uint64_t TimestampInterval(void *ts)
-{
- return ( GET_UA64LE(ts) / TIME_C1 ) * TIME_C2 + TIME_C3;
-}*/
-
-
-/*
- * Creates the HMAC for v6
- */
-static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptSize, int_fast8_t tolerance)
-{
- BYTE hash[32];
-# define halfHashSize (sizeof(hash) >> 1)
- uint64_t timeSlot;
- BYTE *responseEnd = encrypt_start + encryptSize;
-
- // This is the time from the response
- 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.
- // When generating a response tolerance must be 0.
- // If verifying the hash, try tolerance -1, 0 and +1. One of them must match.
-
- timeSlot = LE64( (GET_UA64LE(ft) / TIME_C1 * TIME_C2 + TIME_C3) + (tolerance * TIME_C1) );
-
- // The time slot is hashed with SHA256 so it is not so obvious that it is time
- Sha256((BYTE*) &timeSlot, sizeof(timeSlot), hash);
-
- // The last 16 bytes of the hashed time slot are the actual HMAC key
- if (!Sha256Hmac
- (
- hash + halfHashSize, // Use last 16 bytes of SHA256 as HMAC key
- encrypt_start, // hash only the encrypted part of the v6 response
- encryptSize - sizeof(((RESPONSE_V6*)0)->HMAC), // encryptSize minus the HMAC itself
- hash // use same buffer for resulting hash where the key came from
- ))
- {
- return FALSE;
- }
-
- memcpy(responseEnd - sizeof(((RESPONSE_V6*)0)->HMAC), hash + halfHashSize, halfHashSize);
- return TRUE;
-# undef halfHashSize
-}
-
-
-/*
- * Creates v5 or v6 response
- */
-size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuffer, const char* const ipstr)
-{
- // The response will be created in a fixed sized struct to
- // avoid unaligned access macros and packed structs on RISC systems
- // which largely increase code size.
- //
- // 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;
-
- #ifdef _DEBUG
- RESPONSE_V6_DEBUG* xxx = (RESPONSE_V6_DEBUG*)responseBuffer;
- #endif
-
- static const BYTE DefaultHwid[8] = { HWID };
- int_fast8_t v6 = LE16(request_v6->MajorVer) > 5;
- AesCtx aesCtx;
-
- AesInitKey(&aesCtx, v6 ? AesKeyV6 : AesKeyV5, v6, AES_KEY_BYTES);
- 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);
-
- if (v6) // V6 specific stuff
- {
- // In v6 a random IV is generated
- Response->Version = request_v6->Version;
- get16RandomBytes(Response->IV);
-
- // pre-fill with default HwId (not required for v5)
- 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));
- }
- 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);
- }
-
- // Xor Random bytes with decrypted request IV
- XorBlock(request_v6->IV, Response->RandomXoredIVs);
-
- // Get the base response
- if ( !CreateResponseBase(&request_v6->RequestBase, baseResponse, Response->HwId, ipstr) ) return 0;
-
- // Convert the fixed sized struct into variable sized
- DWORD pidSize = LE32(baseResponse->PIDSize);
- BYTE* postEpidPtr = responseBuffer + V6_PRE_EPID_SIZE + pidSize;
- size_t post_epid_size = v6 ? V6_POST_EPID_SIZE : V5_POST_EPID_SIZE;
-
- memmove(postEpidPtr, &baseResponse->CMID, post_epid_size);
-
- // number of bytes to encrypt
- size_t encryptSize =
- V6_PRE_EPID_SIZE
- - sizeof(Response->Version)
- + pidSize
- + post_epid_size;
-
- //AesDecryptBlock(&aesCtx, Response->IV);
- if (v6 && !CreateV6Hmac(Response->IV, encryptSize, 0)) return 0;
-
- // Padding auto handled by encryption func
- AesEncryptCbc(&aesCtx, NULL, Response->IV, &encryptSize);
-
- return encryptSize + sizeof(Response->Version);
-}
-
-
-// Create Hashed KMS Client Request Data for KMS Protocol Version 4
-BYTE *CreateRequestV4(size_t *size, const REQUEST* requestBase)
-{
- *size = sizeof(REQUEST_V4);
-
- // Build a proper KMS client request data
- BYTE *request = (BYTE *)vlmcsd_malloc(sizeof(REQUEST_V4));
-
- // Temporary Pointer for access to REQUEST_V4 structure
- REQUEST_V4 *request_v4 = (REQUEST_V4 *)request;
-
- // Set KMS Client Request Base
- memcpy(&request_v4->RequestBase, requestBase, sizeof(REQUEST));
-
- // Generate Hash Signature
- AesCmacV4(request, sizeof(REQUEST), request_v4->MAC);
-
- // Return Request Data
- return request;
-}
-
-
-// Create Encrypted KMS Client Request Data for KMS Protocol Version 6
-BYTE* CreateRequestV6(size_t *size, const REQUEST* requestBase)
-{
- *size = sizeof(REQUEST_V6);
-
- // Temporary Pointer for access to REQUEST_V5 structure
- REQUEST_V6 *request = (REQUEST_V6 *)vlmcsd_malloc(sizeof(REQUEST_V6));
-
- // KMS Protocol Version
- request->Version = requestBase->Version;
-
- // Initialize the IV
- get16RandomBytes(request->IV);
-
- // Set KMS Client Request Base
- memcpy(&request->RequestBase, requestBase, sizeof(REQUEST));
-
- // 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);
-
- // Return Proper Request Data
- return (BYTE*)request;
-}
-
-
-/*
- * Checks whether Length of ePID is valid
- */
-static uint8_t checkPidLength(const RESPONSE *const responseBase)
-{
- unsigned int i;
-
- if (LE32(responseBase->PIDSize) > (PID_BUFFER_SIZE << 1)) return FALSE;
- if (responseBase->KmsPID[(LE32(responseBase->PIDSize) >> 1) - 1]) return FALSE;
-
- for (i = 0; i < (LE32(responseBase->PIDSize) >> 1) - 2; i++)
- {
- if (!responseBase->KmsPID[i]) return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- * "Decrypts" a KMS v4 response. Actually just copies to a fixed size buffer
- */
-RESPONSE_RESULT DecryptResponseV4(RESPONSE_V4* response_v4, const int responseSize, BYTE* const rawResponse, const BYTE* const rawRequest)
-{
- int copySize =
- V4_PRE_EPID_SIZE +
- (LE32(((RESPONSE_V4*)rawResponse)->ResponseBase.PIDSize) <= PID_BUFFER_SIZE << 1 ?
- LE32(((RESPONSE_V4*)rawResponse)->ResponseBase.PIDSize) :
- PID_BUFFER_SIZE << 1);
-
- int messageSize = copySize + V4_POST_EPID_SIZE;
-
- memcpy(response_v4, rawResponse, copySize);
- memcpy(&response_v4->ResponseBase.CMID, rawResponse + copySize, responseSize - copySize);
-
- // ensure PID is null terminated
- response_v4->ResponseBase.KmsPID[PID_BUFFER_SIZE-1] = 0;
-
- uint8_t* mac = rawResponse + messageSize;
- AesCmacV4(rawResponse, messageSize, mac);
-
- REQUEST_V4* request_v4 = (REQUEST_V4*)rawRequest;
- RESPONSE_RESULT result;
-
- result.mask = (DWORD)~0;
- result.PidLengthOK = checkPidLength((RESPONSE*)rawResponse);
- result.VersionOK = response_v4->ResponseBase.Version == request_v4->RequestBase.Version;
- result.HashOK = !memcmp(&response_v4->MAC, mac, sizeof(response_v4->MAC));
- result.TimeStampOK = !memcmp(&response_v4->ResponseBase.ClientTime, &request_v4->RequestBase.ClientTime, sizeof(FILETIME));
- result.ClientMachineIDOK = !memcmp(&response_v4->ResponseBase.CMID, &request_v4->RequestBase.CMID, sizeof(GUID));
- result.effectiveResponseSize = responseSize;
- result.correctResponseSize = sizeof(RESPONSE_V4) - sizeof(response_v4->ResponseBase.KmsPID) + LE32(response_v4->ResponseBase.PIDSize);
-
- return result;
-}
-
-
-static RESPONSE_RESULT VerifyResponseV6(RESPONSE_RESULT result, const AesCtx* Ctx, RESPONSE_V6* response_v6, REQUEST_V6* request_v6, BYTE* const rawResponse)
-{
- // Check IVs
- result.IVsOK = !memcmp // In V6 the XoredIV is actually the request IV
- (
- response_v6->XoredIVs,
- request_v6->IV,
- sizeof(response_v6->XoredIVs)
- );
-
- result.IVnotSuspicious = !!memcmp // If IVs are identical, it is obviously an emulator
- (
- request_v6->IV,
- response_v6->IV,
- sizeof(request_v6->IV)
- );
-
- // Check Hmac
- int_fast8_t tolerance;
- BYTE OldHmac[sizeof(response_v6->HMAC)];
-
- result.HmacSha256OK = FALSE;
-
- memcpy // Save received HMAC to compare with calculated HMAC later
- (
- OldHmac,
- response_v6->HMAC,
- sizeof(response_v6->HMAC)
- );
-
- //AesEncryptBlock(Ctx, Response_v6->IV); // CreateV6Hmac needs original IV as received over the network
-
- for (tolerance = -1; tolerance < 2; tolerance++)
- {
- CreateV6Hmac
- (
- rawResponse + sizeof(response_v6->Version), // Pointer to start of the encrypted part of the response
- (size_t)result.correctResponseSize - V6_UNENCRYPTED_SIZE, // size of the encrypted part
- tolerance // tolerance -1, 0, or +1
- );
-
- if
- ((
- result.HmacSha256OK = !memcmp // Compare both HMACs
- (
- OldHmac,
- rawResponse + (size_t)result.correctResponseSize - sizeof(response_v6->HMAC),
- sizeof(OldHmac)
- )
- ))
- {
- break;
- }
- }
- return result;
-}
-
-
-static RESPONSE_RESULT VerifyResponseV5(RESPONSE_RESULT result, REQUEST_V5* request_v5, RESPONSE_V5* response_v5)
-{
- // Check IVs: in V5 (and only v5) request and response IVs must match
- result.IVsOK = !memcmp(request_v5->IV, response_v5->IV, sizeof(request_v5->IV));
-
- // V5 has no Hmac, always set to TRUE
- result.HmacSha256OK = TRUE;
-
- return result;
-}
-
-
-/*
- * Decrypts a KMS v5 or v6 response received from a server.
- * hwid must supply a valid 16 byte buffer for v6. hwid is ignored in v5
- */
-RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BYTE* const response, const BYTE* const rawRequest, BYTE* hwid)
-{
- RESPONSE_RESULT result;
- result.mask = ~0; // Set all bits in the results mask to 1. Assume success first.
- result.effectiveResponseSize = responseSize;
-
- int copySize1 =
- sizeof(response_v6->Version);
-
- // Decrypt KMS Server Response (encrypted part starts after RequestIV)
- responseSize -= copySize1;
-
- AesCtx Ctx;
- 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);
-
- // Check padding
- BYTE* lastPadByte = response + (size_t)result.effectiveResponseSize - 1;
-
- // Must be from 1 to 16
- if (!*lastPadByte || *lastPadByte > AES_BLOCK_BYTES)
- {
- result.DecryptSuccess = FALSE;
- return result;
- }
-
- // Check if pad bytes are all the same
- BYTE* padByte;
- for (padByte = lastPadByte - *lastPadByte + 1; padByte < lastPadByte; padByte++)
- if (*padByte != *lastPadByte)
- {
- result.DecryptSuccess = FALSE;
- return result;
- }
-
- // Add size of Version, KmsPIDLen and variable size PID
- DWORD pidSize = LE32(((RESPONSE_V6*) response)->ResponseBase.PIDSize);
-
- copySize1 +=
- V6_UNENCRYPTED_SIZE +
- sizeof(response_v6->ResponseBase.PIDSize) +
- (pidSize <= PID_BUFFER_SIZE << 1 ? pidSize : PID_BUFFER_SIZE << 1);
-
- // Copy part 1 of response up to variable sized PID
- memcpy(response_v6, response, copySize1);
-
- // ensure PID is null terminated
- response_v6->ResponseBase.KmsPID[PID_BUFFER_SIZE - 1] = 0;
-
- // Copy part 2
- size_t copySize2 = v6 ? V6_POST_EPID_SIZE : V5_POST_EPID_SIZE;
- memcpy(&response_v6->ResponseBase.CMID, response + copySize1, copySize2);
-
- // Decrypting the response is finished here. Now we check the results for validity
- // A basic client doesn't need the stuff below this comment but we want to use vlmcs
- // as a debug tool for KMS emulators.
-
- REQUEST_V6* request_v6 = (REQUEST_V6*) rawRequest;
- DWORD decryptSize = sizeof(request_v6->IV) + sizeof(request_v6->RequestBase) + sizeof(request_v6->Pad);
-
- AesDecryptCbc(&Ctx, NULL, request_v6->IV, decryptSize);
-
- // Check that all version informations are the same
- result.VersionOK =
- request_v6->Version == response_v6->ResponseBase.Version &&
- request_v6->Version == response_v6->Version &&
- request_v6->Version == request_v6->RequestBase.Version;
-
- // Check Base Request
- result.PidLengthOK = checkPidLength(&((RESPONSE_V6*) response)->ResponseBase);
- result.TimeStampOK = !memcmp(&response_v6->ResponseBase.ClientTime, &request_v6->RequestBase.ClientTime, sizeof(FILETIME));
- 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)];
-
- 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));
-
- // size before encryption (padding not included)
- result.correctResponseSize =
- (v6 ? sizeof(RESPONSE_V6) : sizeof(RESPONSE_V5))
- - sizeof(response_v6->ResponseBase.KmsPID)
- + LE32(response_v6->ResponseBase.PIDSize);
-
- // Version specific stuff
- if (v6)
- {
- // Copy the HwId
- memcpy(hwid, response_v6->HwId, sizeof(response_v6->HwId));
-
- // Verify the V6 specific part of the response
- result = VerifyResponseV6(result, &Ctx, response_v6, request_v6, response);
- }
- else // V5
- {
- // Verify the V5 specific part of the response
- result = VerifyResponseV5(result, request_v6, (RESPONSE_V5*)response_v6);
- }
-
- // padded size after encryption
- result.correctResponseSize += (~(result.correctResponseSize - sizeof(response_v6->ResponseBase.Version)) & 0xf) + 1;
-
- return result;
-}
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "endian.h"
-
-#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \
- && defined(BS16) && defined(BS32) && defined(BS64)
-
-#else // ! defined(__BYTE_ORDER)
-
-void PUT_UAA64BE(void *p, unsigned long long v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- _p[ 0 ] = v >> 56;
- _p[ 1 ] = v >> 48;
- _p[ 2 ] = v >> 40;
- _p[ 3 ] = v >> 32;
- _p[ 4 ] = v >> 24;
- _p[ 5 ] = v >> 16;
- _p[ 6 ] = v >> 8;
- _p[ 7 ] = v;
-}
-
-void PUT_UAA32BE(void *p, unsigned int v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- _p[ 0 ] = v >> 24;
- _p[ 1 ] = v >> 16;
- _p[ 2 ] = v >> 8;
- _p[ 3 ] = v;
-}
-
-void PUT_UAA16BE(void *p, unsigned short v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- _p[ 0 ] = v >> 8;
- _p[ 1 ] = v;
-}
-
-
-void PUT_UAA64LE(void *p, unsigned long long v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- _p[ 0 ] = v;
- _p[ 1 ] = v >> 8;
- _p[ 2 ] = v >> 16;
- _p[ 3 ] = v >> 24;
- _p[ 4 ] = v >> 32;
- _p[ 5 ] = v >> 40;
- _p[ 6 ] = v >> 48;
- _p[ 7 ] = v >> 56;
-}
-
-void PUT_UAA32LE(void *p, unsigned int v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- _p[ 0 ] = v;
- _p[ 1 ] = v >> 8;
- _p[ 2 ] = v >> 16;
- _p[ 3 ] = v >> 24;
-}
-
-void PUT_UAA16LE(void *p, unsigned short v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- _p[ 0 ] = v;
- _p[ 1 ] = v >> 8;
-}
-
-
-unsigned long long GET_UAA64BE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- return
- (unsigned long long)_p[ 0 ] << 56 |
- (unsigned long long)_p[ 1 ] << 48 |
- (unsigned long long)_p[ 2 ] << 40 |
- (unsigned long long)_p[ 3 ] << 32 |
- (unsigned long long)_p[ 4 ] << 24 |
- (unsigned long long)_p[ 5 ] << 16 |
- (unsigned long long)_p[ 6 ] << 8 |
- (unsigned long long)_p[ 7 ];
-
-}
-
-unsigned int GET_UAA32BE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- return
- (unsigned int)_p[ 0 ] << 24 |
- (unsigned int)_p[ 1 ] << 16 |
- (unsigned int)_p[ 2 ] << 8 |
- (unsigned int)_p[ 3 ];
-}
-
-unsigned short GET_UAA16BE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- return
- (unsigned short)_p[ 0 ] << 8 |
- (unsigned short)_p[ 1 ];
-}
-
-
-unsigned long long GET_UAA64LE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- return
- (unsigned long long)_p[ 0 ] |
- (unsigned long long)_p[ 1 ] << 8 |
- (unsigned long long)_p[ 2 ] << 16 |
- (unsigned long long)_p[ 3 ] << 24 |
- (unsigned long long)_p[ 4 ] << 32 |
- (unsigned long long)_p[ 5 ] << 40 |
- (unsigned long long)_p[ 6 ] << 48 |
- (unsigned long long)_p[ 7 ] << 56;
-
-}
-
-unsigned int GET_UAA32LE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- return
- (unsigned int)_p[ 0 ] |
- (unsigned int)_p[ 1 ] << 8 |
- (unsigned int)_p[ 2 ] << 16 |
- (unsigned int)_p[ 3 ] << 24;
-}
-
-unsigned short GET_UAA16LE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- return
- (unsigned short)_p[ 0 ] |
- (unsigned short)_p[ 1 ] << 8;
-}
-
-
-unsigned short BE16(unsigned short x)
-{
- return GET_UAA16BE(&x, 0);
-}
-
-unsigned short LE16(unsigned short x)
-{
- return GET_UAA16LE(&x, 0);
-}
-
-unsigned int BE32(unsigned int x)
-{
- return GET_UAA32BE(&x, 0);
-}
-
-unsigned int LE32(unsigned int x)
-{
- return GET_UAA32LE(&x, 0);
-}
-
-unsigned long long BE64(unsigned long long x)
-{
- return GET_UAA64BE(&x, 0);
-}
-
-inline unsigned long long LE64(unsigned long long x)
-{
- return GET_UAA64LE(&x, 0);
-}
-
-#endif // defined(__BYTE_ORDER)
-#ifndef _DEFAULT_SOURCE
-#define _DEFAULT_SOURCE
-#endif // _DEFAULT_SOURCE
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "output.h"
-#include "shared_globals.h"
-#include "endian.h"
-#include "helpers.h"
-
-#ifndef NO_LOG
-static void vlogger(const char *message, va_list args)
-{
- FILE *log;
-
- #ifdef _NTSERVICE
- if (!IsNTService && logstdout) log = stdout;
- #else
- if (logstdout) log = stdout;
- #endif
- else
- {
- if (fn_log == NULL) return;
-
- #ifndef _WIN32
- if (!strcmp(fn_log, "syslog"))
- {
- openlog("vlmcsd", LOG_CONS | LOG_PID, LOG_USER);
-
- ////PORTABILITY: vsyslog is not in Posix but virtually all Unixes have it
- vsyslog(LOG_INFO, message, args);
-
- closelog();
- return;
- }
- #endif // _WIN32
-
- log = fopen(fn_log, "a");
- if ( !log ) return;
- }
-
- time_t now = time(0);
-
- #ifdef USE_THREADS
- char mbstr[2048];
- #else
- char mbstr[24];
- #endif
-
- strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", localtime(&now));
-
- #ifndef USE_THREADS
-
- fprintf(log, "%s: ", mbstr);
- vfprintf(log, message, args);
- fflush(log);
-
- #else // USE_THREADS
-
- // We write everything to a string before we really log inside the critical section
- // so formatting the output can be concurrent
- strcat(mbstr, ": ");
- int len = strlen(mbstr);
- vsnprintf(mbstr + len, sizeof(mbstr) - len, message, args);
-
- lock_mutex(&logmutex);
- fputs(mbstr, log);
- fflush(log);
- unlock_mutex(&logmutex);
-
- #endif // USE_THREADS
- if (log != stdout) fclose(log);
-}
-
-
-// Always sends to log output
-int logger(const char *const fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- vlogger(fmt, args);
- va_end(args);
- return 0;
-}
-
-#endif //NO_LOG
-
-
-// Output to stderr if it is available or to log otherwise (e.g. if running as daemon/service)
-void printerrorf(const char *const fmt, ...)
-{
- va_list arglist;
-
- va_start(arglist, fmt);
-
- #ifndef NO_LOG
- #ifdef _NTSERVICE
- if (InetdMode || IsNTService)
- #else // !_NTSERVICE
- if (InetdMode)
- #endif // NTSERVIICE
- vlogger(fmt, arglist);
- else
- #endif //NO_LOG
- {
- vfprintf(stderr, fmt, arglist);
- fflush(stderr);
- }
-
- va_end(arglist);
-}
-
-
-// Always output to stderr
-int errorout(const char* fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- int i = vfprintf(stderr, fmt, args);
- va_end(args);
- fflush(stderr);
-
- return i;
-}
-
-
-static const char *LicenseStatusText[] =
-{
- "Unlicensed", "Licensed", "OOB grace", "OOT grace", "Non-Genuine", "Notification", "Extended grace"
-};
-
-
-void uuid2StringLE(const GUID *const guid, char *const string)
-{
- sprintf(string,
- #ifdef _WIN32
- "%08x-%04x-%04x-%04x-%012I64x",
- #else
- "%08x-%04x-%04x-%04x-%012llx",
- #endif
- (unsigned int)LE32( guid->Data1 ),
- (unsigned int)LE16( guid->Data2 ),
- (unsigned int)LE16( guid->Data3 ),
- (unsigned int)BE16( *(uint16_t*)guid->Data4 ),
- (unsigned long long)BE64(*(uint64_t*)(guid->Data4)) & 0xffffffffffffLL
- );
-}
-
-
-void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p)
-{
- char guidBuffer[GUID_STRING_LENGTH + 1];
- char WorkstationBuffer[3 * WORKSTATION_NAME_BUFFER];
- const char *productName;
- ProdListIndex_t index;
-
- p("Protocol version : %u.%u\n", LE16(Request->MajorVer), LE16(Request->MinorVer));
- p("Client is a virtual machine : %s\n", LE32(Request->VMInfo) ? "Yes" : "No");
- p("Licensing status : %u (%s)\n", (uint32_t)LE32(Request->LicenseStatus), LE32(Request->LicenseStatus) < _countof(LicenseStatusText) ? LicenseStatusText[LE32(Request->LicenseStatus)] : "Unknown");
- p("Remaining time (0 = forever) : %i minutes\n", (uint32_t)LE32(Request->BindingExpiration));
-
- uuid2StringLE(&Request->AppID, guidBuffer);
- productName = getProductNameLE(&Request->AppID, AppList, &index);
- p("Application ID : %s (%s)\n", guidBuffer, productName);
-
- uuid2StringLE(&Request->ActID, guidBuffer);
-
- #ifndef NO_EXTENDED_PRODUCT_LIST
- productName = getProductNameLE(&Request->ActID, ExtendedProductList, &index);
- #else
- productName = "Unknown";
- #endif
-
- p("Activation ID (Product) : %s (%s)\n", guidBuffer, productName);
-
- uuid2StringLE(&Request->KMSID, guidBuffer);
-
- #ifndef NO_BASIC_PRODUCT_LIST
- productName = getProductNameLE(&Request->KMSID, ProductList, &index);
- #else
- productName = "Unknown";
- #endif
-
- p("Key Management Service ID : %s (%s)\n", guidBuffer, productName);
-
- uuid2StringLE(&Request->CMID, guidBuffer);
- p("Client machine ID : %s\n", guidBuffer);
-
- uuid2StringLE(&Request->CMID_prev, guidBuffer);
- p("Previous client machine ID : %s\n", guidBuffer);
-
-
- char mbstr[64];
- time_t st;
- st = fileTimeToUnixTime(&Request->ClientTime);
- strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", gmtime(&st));
- p("Client request timestamp (UTC) : %s\n", mbstr);
-
- ucs2_to_utf8(Request->WorkstationName, WorkstationBuffer, WORKSTATION_NAME_BUFFER, sizeof(WorkstationBuffer));
-
- p("Workstation name : %s\n", WorkstationBuffer);
- 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)
-{
- char guidBuffer[GUID_STRING_LENGTH + 1];
- //SYSTEMTIME st;
-
- p("Protocol version : %u.%u\n", (uint32_t)LE16(response->MajorVer), (uint32_t)LE16(response->MinorVer));
- p("KMS host extended PID : %s\n", ePID);
- if (LE16(response->MajorVer) > 5)
-# ifndef _WIN32
- p("KMS host Hardware ID : %016llX\n", (unsigned long long)BE64(*(uint64_t*)hwid));
-# else // _WIN32
- p("KMS host Hardware ID : %016I64X\n", (unsigned long long)BE64(*(uint64_t*)hwid));
-# endif // WIN32
-
- uuid2StringLE(&response->CMID, guidBuffer);
- p("Client machine ID : %s\n", guidBuffer);
-
- char mbstr[64];
- time_t st;
-
- st = fileTimeToUnixTime(&response->ClientTime);
- strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", gmtime(&st));
- p("Client request timestamp (UTC) : %s\n", mbstr);
-
- p("KMS host current active clients : %u\n", (uint32_t)LE32(response->Count));
- p("Renewal interval policy : %u\n", (uint32_t)LE32(response->VLRenewalInterval));
- p("Activation interval policy : %u\n", (uint32_t)LE32(response->VLActivationInterval));
-}
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "shared_globals.h"
-
-int global_argc, multi_argc = 0;
-CARGV global_argv, multi_argv = NULL;
-const char *const Version = VERSION;
-DWORD VLActivationInterval = 60 * 2; // 2 hours
-DWORD VLRenewalInterval = 60 * 24 * 7; // 7 days
-int_fast8_t DisconnectImmediately = FALSE;
-const char *const cIPv4 = "IPv4";
-const char *const cIPv6 = "IPv6";
-
-#ifndef USE_MSRPC
-int_fast8_t UseMultiplexedRpc = TRUE;
-int_fast8_t UseRpcNDR64 = TRUE;
-int_fast8_t UseRpcBTFN = TRUE;
-#endif // USE_MSRPC
-
-#ifndef NO_SOCKETS
-const char *defaultport = "1688";
-#endif // NO_SOCKETS
-
-KmsResponseParam_t KmsResponseParameters[MAX_KMSAPPS];
-
-#if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
-int_fast8_t IsRestarted = FALSE;
-#endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
-
-#if !defined(NO_TIMEOUT) && !__minix__
-DWORD ServerTimeout = 30;
-#endif // !defined(NO_TIMEOUT) && !__minix__
-
-#if !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-#ifdef USE_MSRPC
-uint32_t MaxTasks = RPC_C_LISTEN_MAX_CALLS_DEFAULT;
-#else // !USE_MSRPC
-uint32_t MaxTasks = SEM_VALUE_MAX;
-#endif // !USE_MSRPC
-#endif // !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-
-#ifndef NO_LOG
-char *fn_log = NULL;
-int_fast8_t logstdout = 0;
-#ifndef NO_VERBOSE_LOG
-int_fast8_t logverbose = 0;
-#endif // NO_VERBOSE_LOG
-#endif // NO_LOG
-
-#ifndef NO_SOCKETS
-int_fast8_t nodaemon = 0;
-int_fast8_t InetdMode = 0;
-#else
-int_fast8_t nodaemon = 1;
-int_fast8_t InetdMode = 1;
-#endif
-
-#ifndef NO_RANDOM_EPID
-int_fast8_t RandomizationLevel = 1;
-uint16_t Lcid = 0;
-#endif
-
-#ifndef NO_SOCKETS
-SOCKET *SocketList;
-int numsockets = 0;
-
-#if !defined(NO_LIMIT) && !__minix__
-#ifndef _WIN32 // Posix
-sem_t *Semaphore;
-#else // _WIN32
-HANDLE Semaphore;
-#endif // _WIN32
-
-#endif // !defined(NO_LIMIT) && !__minix__
-#endif // NO_SOCKETS
-
-#ifdef _NTSERVICE
-int_fast8_t IsNTService = TRUE;
-int_fast8_t ServiceShutdown = FALSE;
-#endif // _NTSERVICE
-
-#ifndef NO_LOG
-#ifdef USE_THREADS
-#if !defined(_WIN32) && !defined(__CYGWIN__)
-pthread_mutex_t logmutex = PTHREAD_MUTEX_INITIALIZER;
-#else
-CRITICAL_SECTION logmutex;
-#endif // !defined(_WIN32) && !defined(__CYGWIN__)
-#endif // USE_THREADS
-#endif // NO_LOG
-
-
-
-
-
-/*
- * Helper functions used by other modules
- */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef _WIN32
-#include
-#endif // _WIN32
-#include
-#include
-#include
-#include
-#include "helpers.h"
-#include "output.h"
-#include "endian.h"
-#include "shared_globals.h"
-
-
-/*
- * UCS2 <-> UTF-8 functions
- * All functions use little endian UCS2 since we only need it to communicate with Windows via RPC
- */
-
-// Convert one character from UTF-8 to UCS2
-// Returns 0xffff, if utf-8 evaluates to > 0xfffe (outside basic multilingual pane)
-WCHAR utf8_to_ucs2_char (const unsigned char *input, const unsigned char **end_ptr)
-{
- *end_ptr = input;
- if (input[0] == 0)
- return ~0;
-
- if (input[0] < 0x80) {
- *end_ptr = input + 1;
- return LE16(input[0]);
- }
-
- if ((input[0] & 0xE0) == 0xE0) {
-
- if (input[1] == 0 || input[2] == 0)
- return ~0;
-
- *end_ptr = input + 3;
-
- return
- LE16((input[0] & 0x0F)<<12 |
- (input[1] & 0x3F)<<6 |
- (input[2] & 0x3F));
- }
-
- if ((input[0] & 0xC0) == 0xC0) {
- if (input[1] == 0)
- return ~0;
-
- *end_ptr = input + 2;
-
- return
- LE16((input[0] & 0x1F)<<6 |
- (input[1] & 0x3F));
- }
- return ~0;
-}
-
-// Convert one character from UCS2 to UTF-8
-// Returns length of UTF-8 char (1, 2 or 3) or -1 on error (UTF-16 outside UCS2)
-// char *utf8 must be large enough to hold 3 bytes
-int ucs2_to_utf8_char (const WCHAR ucs2_le, char *utf8)
-{
- const WCHAR ucs2 = LE16(ucs2_le);
-
- if (ucs2 < 0x80) {
- utf8[0] = ucs2;
- utf8[1] = '\0';
- return 1;
- }
-
- if (ucs2 >= 0x80 && ucs2 < 0x800) {
- utf8[0] = (ucs2 >> 6) | 0xC0;
- utf8[1] = (ucs2 & 0x3F) | 0x80;
- utf8[2] = '\0';
- return 2;
- }
-
- if (ucs2 >= 0x800 && ucs2 < 0xFFFF) {
-
- if (ucs2 >= 0xD800 && ucs2 <= 0xDFFF) {
- /* Ill-formed (UTF-16 ouside of BMP) */
- return -1;
- }
-
- utf8[0] = ((ucs2 >> 12) ) | 0xE0;
- utf8[1] = ((ucs2 >> 6 ) & 0x3F) | 0x80;
- utf8[2] = ((ucs2 ) & 0x3F) | 0x80;
- utf8[3] = '\0';
- return 3;
- }
-
- return -1;
-}
-
-
-// Converts UTF8 to UCS2. Returns size in bytes of the converted string or -1 on error
-size_t utf8_to_ucs2(WCHAR* const ucs2_le, const char* const utf8, const size_t maxucs2, const size_t maxutf8)
-{
- const unsigned char* current_utf8 = (unsigned char*)utf8;
- WCHAR* current_ucs2_le = ucs2_le;
-
- for (; *current_utf8; current_ucs2_le++)
- {
- size_t size = (char*)current_utf8 - utf8;
-
- if (size >= maxutf8) return (size_t)-1;
- if (((*current_utf8 & 0xc0) == 0xc0) && (size >= maxutf8 - 1)) return (size_t)-1;
- if (((*current_utf8 & 0xe0) == 0xe0) && (size >= maxutf8 - 2)) return (size_t)-1;
- if (current_ucs2_le - ucs2_le >= (intptr_t)maxucs2 - 1) return (size_t)-1;
-
- *current_ucs2_le = utf8_to_ucs2_char(current_utf8, ¤t_utf8);
- current_ucs2_le[1] = 0;
-
- if (*current_ucs2_le == (WCHAR)-1) return (size_t)-1;
- }
- return current_ucs2_le - ucs2_le;
-}
-
-// Converts UCS2 to UTF-8. Return TRUE or FALSE
-BOOL ucs2_to_utf8(const WCHAR* const ucs2_le, char* utf8, size_t maxucs2, size_t maxutf8)
-{
- char utf8_char[4];
- const WCHAR* current_ucs2 = ucs2_le;
- unsigned int index_utf8 = 0;
-
- for(*utf8 = 0; *current_ucs2; current_ucs2++)
- {
- if (current_ucs2 - ucs2_le > (intptr_t)maxucs2) return FALSE;
- int len = ucs2_to_utf8_char(*current_ucs2, utf8_char);
- if (index_utf8 + len > maxutf8) return FALSE;
- strncat(utf8, utf8_char, len);
- index_utf8+=len;
- }
-
- return TRUE;
-}
-
-/* End of UTF-8 <-> UCS2 conversion */
-
-
-// Checks, whether a string is a valid integer number between min and max. Returns TRUE or FALSE. Puts int value in *value
-BOOL stringToInt(const char *const szValue, const unsigned int min, const unsigned int max, unsigned int *const value)
-{
- char *nextchar;
-
- errno = 0;
- long long result = strtoll(szValue, &nextchar, 10);
-
- if (errno || result < (long long)min || result > (long long)max || *nextchar)
- {
- return FALSE;
- }
-
- *value = (unsigned int)result;
- return TRUE;
-}
-
-
-//Converts a String Guid to a host binary guid in host endianess
-int_fast8_t string2Uuid(const char *const restrict input, GUID *const restrict guid)
-{
- int i;
-
- if (strlen(input) < GUID_STRING_LENGTH) return FALSE;
- if (input[8] != '-' || input[13] != '-' || input[18] != '-' || input[23] != '-') return FALSE;
-
- for (i = 0; i < GUID_STRING_LENGTH; i++)
- {
- if (i == 8 || i == 13 || i == 18 || i == 23) continue;
-
- const char c = toupper((int)input[i]);
-
- if (c < '0' || c > 'F' || (c > '9' && c < 'A')) return FALSE;
- }
-
- char inputCopy[GUID_STRING_LENGTH + 1];
- strncpy(inputCopy, input, GUID_STRING_LENGTH + 1);
- inputCopy[8] = inputCopy[13] = inputCopy[18] = 0;
-
- hex2bin((BYTE*)&guid->Data1, inputCopy, 8);
- hex2bin((BYTE*)&guid->Data2, inputCopy + 9, 4);
- hex2bin((BYTE*)&guid->Data3, inputCopy + 14, 4);
- hex2bin(guid->Data4, input + 19, 16);
-
- guid->Data1 = BE32(guid->Data1);
- guid->Data2 = BE16(guid->Data2);
- guid->Data3 = BE16(guid->Data3);
- return TRUE;
-}
-
-
-// convert GUID to little-endian
-void LEGUID(GUID *const restrict out, const GUID* const restrict in)
-{
- #if __BYTE_ORDER != __LITTLE_ENDIAN
- out->Data1 = LE32(in->Data1);
- out->Data2 = LE16(in->Data2);
- out->Data3 = LE16(in->Data3);
- memcpy(out->Data4, in->Data4, sizeof(out->Data4));
- #else
- memcpy(out, in, sizeof(GUID));
- #endif
-}
-
-
-//Checks a command line argument if it is numeric and between min and max. Returns the numeric value or exits on error
-__pure unsigned int getOptionArgumentInt(const char o, const unsigned int min, const unsigned int max)
-{
- unsigned int result;
-
- if (!stringToInt(optarg, min, max, &result))
- {
- printerrorf("Fatal: Option \"-%c\" must be numeric between %u and %u.\n", o, min, max);
- exit(!0);
- }
-
- return result;
-}
-
-
-// Resets getopt() to start parsing from the beginning
-void optReset(void)
-{
- #if __minix__ || defined(__BSD__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
- optind = 1;
- optreset = 1; // Makes newer BSD getopt happy
- #elif defined(__UCLIBC__) // uClibc headers also define __GLIBC__ so be careful here
- optind = 0; // uClibc seeks compatibility with GLIBC
- #elif defined(__GLIBC__)
- optind = 0; // Makes GLIBC getopt happy
- #else // Standard for most systems
- optind = 1;
- #endif
-}
-
-
-#if defined(_WIN32) || defined(USE_MSRPC)
-
-// Returns a static message buffer containing text for a given Win32 error. Not thread safe (same as strerror)
-char* win_strerror(const int message)
-{
- #define STRERROR_BUFFER_SIZE 256
- static char buffer[STRERROR_BUFFER_SIZE];
-
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, message, 0, buffer, STRERROR_BUFFER_SIZE, NULL);
- return buffer;
-}
-
-#endif // defined(_WIN32) || defined(USE_MSRPC)
-
-
-/*
- * parses an address in the form host:[port] in addr
- * returns host and port in seperate strings
- */
-void parseAddress(char *const addr, char** szHost, char** szPort)
-{
- *szHost = addr;
-
-# ifndef NO_SOCKETS
- *szPort = (char*)defaultport;
-# else // NO_SOCKETS
- *szPort = "1688";
-# endif // NO_SOCKETS
-
- char *lastcolon = strrchr(addr, ':');
- char *firstcolon = strchr(addr, ':');
- char *closingbracket = strrchr(addr, ']');
-
- if (*addr == '[' && closingbracket) //Address in brackets
- {
- *closingbracket = 0;
- (*szHost)++;
-
- if (closingbracket[1] == ':')
- *szPort = closingbracket + 2;
- }
- else if (firstcolon && firstcolon == lastcolon) //IPv4 address or hostname with port
- {
- *firstcolon = 0;
- *szPort = firstcolon + 1;
- }
-}
-
-
-// Initialize random generator (needs to be done in each thread)
-void randomNumberInit()
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- srand((unsigned int)(tv.tv_sec ^ tv.tv_usec));
-}
-
-
-// We always exit immediately if any OOM condition occurs
-__noreturn void OutOfMemory(void)
-{
- errorout("Fatal: Out of memory");
- exit(!0);
-}
-
-
-void* vlmcsd_malloc(size_t len)
-{
- void* buf = malloc(len);
- if (!buf) OutOfMemory();
- return buf;
-}
-
-
-/*
- * Converts hex digits to bytes in big-endian order.
- * Ignores any non-hex characters
- */
-void hex2bin(BYTE *const bin, const char *hex, const size_t maxbin)
-{
- static const char *const hexdigits = "0123456789ABCDEF";
- char* nextchar;
- size_t i;
-
- for (i = 0; (i < 16) && utf8_to_ucs2_char((const unsigned char*)hex, (const unsigned char**)&nextchar) != (WCHAR)-1; hex = nextchar)
- {
- const char* pos = strchr(hexdigits, toupper((int)*hex));
- if (!pos) continue;
-
- if (!(i & 1)) bin[i >> 1] = 0;
- bin[i >> 1] |= (char)(pos - hexdigits);
- if (!(i & 1)) bin[i >> 1] <<= 4;
- i++;
- if (i >> 1 > maxbin) break;
- }
-}
-
-
-__pure BOOL getArgumentBool(int_fast8_t *result, const char *const argument)
-{
- if (
- !strncasecmp(argument, "true", 4) ||
- !strncasecmp(argument, "on", 2) ||
- !strncasecmp(argument, "yes", 3) ||
- !strncasecmp(argument, "1", 1)
- )
- {
- *result = TRUE;
- return TRUE;
- }
- else if (
- !strncasecmp(argument, "false", 5) ||
- !strncasecmp(argument, "off", 3) ||
- !strncasecmp(argument, "no", 2) ||
- !strncasecmp(argument, "0", 1)
- )
- {
- *result = FALSE;
- return TRUE;
- }
-
- return FALSE;
-}
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef USE_MSRPC
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include
-#ifndef _WIN32
-#include
-#include
-#include
-#include
-#include
-#endif // WIN32
-
-#include "network.h"
-#include "endian.h"
-#include "output.h"
-#include "helpers.h"
-#include "shared_globals.h"
-#include "rpc.h"
-
-
-#ifndef _WIN32
-typedef ssize_t (*sendrecv_t)(int, void*, size_t, int);
-#else
-typedef int (WINAPI *sendrecv_t)(SOCKET, void*, int, int);
-#endif
-
-
-// Send or receive a fixed number of bytes regardless if received in one or more chunks
-int_fast8_t sendrecv(SOCKET sock, BYTE *data, int len, int_fast8_t do_send)
-{
- int n;
- sendrecv_t f = do_send
- ? (sendrecv_t) send
- : (sendrecv_t) recv;
-
- do
- {
- n = f(sock, data, len, 0);
- }
- while (
- ( n < 0 && socket_errno == VLMCSD_EINTR ) || ( n > 0 && ( data += n, (len -= n) > 0 ) ));
-
- return ! len;
-}
-
-
-static int_fast8_t ip2str(char *restrict result, const size_t resultLength, const struct sockaddr *const restrict socketAddress, const socklen_t socketLength)
-{
- static const char *const fIPv4 = "%s:%s";
- static const char *const fIPv6 = "[%s]:%s";
- char ipAddress[64], portNumber[8];
-
- if (getnameinfo
- (
- socketAddress,
- socketLength,
- ipAddress,
- sizeof(ipAddress),
- portNumber,
- sizeof(portNumber),
- NI_NUMERICHOST | NI_NUMERICSERV
- ))
- {
- return FALSE;
- }
-
- if ((unsigned int)snprintf(result, resultLength, socketAddress->sa_family == AF_INET6 ? fIPv6 : fIPv4, ipAddress, portNumber) > resultLength) return FALSE;
- return TRUE;
-}
-
-
-static int_fast8_t getSocketList(struct addrinfo **saList, const char *const addr, const int flags, const int AddressFamily)
-{
- int status;
- char *szHost, *szPort;
- size_t len = strlen(addr) + 1;
-
- // Don't alloca too much
- if (len > 264) return FALSE;
-
- char *addrcopy = (char*)alloca(len);
- memcpy(addrcopy, addr, len);
-
- parseAddress(addrcopy, &szHost, &szPort);
-
- struct addrinfo hints;
-
- memset(&hints, 0, sizeof(struct addrinfo));
-
- hints.ai_family = AddressFamily;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_flags = flags;
-
- if ((status = getaddrinfo(szHost, szPort, &hints, saList)))
- {
- printerrorf("Warning: %s: %s\n", addr, gai_strerror(status));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-static int_fast8_t setBlockingEnabled(SOCKET fd, int_fast8_t blocking)
-{
- if (fd == INVALID_SOCKET) return FALSE;
-
- #ifdef _WIN32
-
- unsigned long mode = blocking ? 0 : 1;
- return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? TRUE : FALSE;
-
- #else // POSIX
-
- int flags = fcntl(fd, F_GETFL, 0);
-
- if (flags < 0) return FALSE;
-
- flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
- return (fcntl(fd, F_SETFL, flags) == 0) ? TRUE : FALSE;
-
- #endif // POSIX
-}
-
-
-int_fast8_t isDisconnected(const SOCKET s)
-{
- char buffer[1];
-
- if (!setBlockingEnabled(s, FALSE)) return TRUE;
-
- int n = recv(s, buffer, 1, MSG_PEEK);
-
- if (!setBlockingEnabled(s, TRUE)) return TRUE;
- if (n == 0) return TRUE;
-
- return FALSE;
-}
-
-
-// Connect to TCP address addr (e.g. "kms.example.com:1688") and return an
-// open socket for the connection if successful or INVALID_SOCKET otherwise
-SOCKET connectToAddress(const char *const addr, const int AddressFamily, int_fast8_t showHostName)
-{
- struct addrinfo *saList, *sa;
- SOCKET s = INVALID_SOCKET;
- char szAddr[128];
-
- if (!getSocketList(&saList, addr, 0, AddressFamily)) return INVALID_SOCKET;
-
- for (sa = saList; sa; sa = sa->ai_next)
- {
- // struct sockaddr_in* addr4 = (struct sockaddr_in*)sa->ai_addr;
- // struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sa->ai_addr;
-
- if (ip2str(szAddr, sizeof(szAddr), sa->ai_addr, sa->ai_addrlen))
- {
- if (showHostName)
- printf("Connecting to %s (%s) ... ", addr, szAddr);
- else
- printf("Connecting to %s ... ", szAddr);
-
- fflush(stdout);
- }
-
- s = socket(sa->ai_family, SOCK_STREAM, IPPROTO_TCP);
-
-# if !defined(NO_TIMEOUT) && !__minix__
-# ifndef _WIN32 // Standard Posix timeout structure
-
- struct timeval to;
- to.tv_sec = 10;
- to.tv_usec = 0;
-
-# else // Windows requires a DWORD with milliseconds
-
- DWORD to = 10000;
-
-# endif // _WIN32
-
- setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to));
- setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
-# endif // !defined(NO_TIMEOUT) && !__minix__
-
- if (!connect(s, sa->ai_addr, sa->ai_addrlen))
- {
- printf("successful\n");
- break;
- }
-
- errorout("%s\n", socket_errno == VLMCSD_EINPROGRESS ? "Timed out" : vlmcsd_strerror(socket_errno));
-
- socketclose(s);
- s = INVALID_SOCKET;
- }
-
- freeaddrinfo(saList);
- return s;
-}
-
-
-#ifndef NO_SOCKETS
-
-// Create a Listening socket for addrinfo sa and return socket s
-// szHost and szPort are for logging only
-static int listenOnAddress(const struct addrinfo *const ai, SOCKET *s)
-{
- int error;
- char ipstr[64];
-
- ip2str(ipstr, sizeof(ipstr), ai->ai_addr, ai->ai_addrlen);
-
- //*s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- *s = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
-
- if (*s == INVALID_SOCKET)
- {
- error = socket_errno;
- printerrorf("Warning: %s error. %s\n", ai->ai_family == AF_INET6 ? cIPv6 : cIPv4, vlmcsd_strerror(error));
- return error;
- }
-
-# if !defined(_WIN32) && !defined(NO_SIGHUP)
-
- int flags = fcntl(*s, F_GETFD, 0);
-
- if (flags != -1)
- {
- flags |= FD_CLOEXEC;
- fcntl(*s, F_SETFD, flags);
- }
-# ifdef _PEDANTIC
- else
- {
- printerrorf("Warning: Could not set FD_CLOEXEC flag on %s: %s\n", ipstr, vlmcsd_strerror(errno));
- }
-# endif // _PEDANTIC
-
-# endif // !defined(_WIN32) && !defined(NO_SIGHUP)
-
- BOOL socketOption = TRUE;
-
- // fix for lame tomato toolchain
-# ifndef IPV6_V6ONLY
-# ifdef __linux__
-# define IPV6_V6ONLY (26)
-# endif // __linux__
-# endif // IPV6_V6ONLY
-
-# ifdef IPV6_V6ONLY
- if (ai->ai_family == AF_INET6) setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_t)&socketOption, sizeof(socketOption));
-# endif
-
-# ifndef _WIN32
- setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (sockopt_t)&socketOption, sizeof(socketOption));
-# endif
-
- if (bind(*s, ai->ai_addr, ai->ai_addrlen) || listen(*s, SOMAXCONN))
- {
- error = socket_errno;
- printerrorf("Warning: %s: %s\n", ipstr, vlmcsd_strerror(error));
- socketclose(*s);
- return error;
- }
-
-# ifndef NO_LOG
- logger("Listening on %s\n", ipstr);
-# endif
-
- return 0;
-}
-
-
-// Adds a listening socket for an address string,
-// e.g. 127.0.0.1:1688 or [2001:db8:dead:beef::1]:1688
-BOOL addListeningSocket(const char *const addr)
-{
- struct addrinfo *aiList, *ai;
- int result = FALSE;
- SOCKET *s = SocketList + numsockets;
-
- if (getSocketList(&aiList, addr, AI_PASSIVE | AI_NUMERICHOST, AF_UNSPEC))
- {
- for (ai = aiList; ai; ai = ai->ai_next)
- {
- // struct sockaddr_in* addr4 = (struct sockaddr_in*)sa->ai_addr;
- // struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sa->ai_addr;
-
- if (numsockets >= FD_SETSIZE)
- {
- #ifdef _PEDANTIC // Do not report this error in normal builds to keep file size low
- printerrorf("Warning: Cannot listen on %s. Your OS only supports %u listening sockets in an FD_SET.\n", addr, FD_SETSIZE);
- #endif
- break;
- }
-
- if (!listenOnAddress(ai, s))
- {
- numsockets++;
- result = TRUE;
- }
- }
-
- freeaddrinfo(aiList);
- }
- return result;
-}
-
-
-// Just create some dummy sockets to see if we have a specific protocol (IPv4 or IPv6)
-__pure int_fast8_t checkProtocolStack(const int addressfamily)
-{
- SOCKET s; // = INVALID_SOCKET;
-
- s = socket(addressfamily, SOCK_STREAM, 0);
- int_fast8_t success = (s != INVALID_SOCKET);
-
- socketclose(s);
- return success;
-}
-
-
-// Build an fd_set of all listening socket then use select to wait for an incoming connection
-static SOCKET network_accept_any()
-{
- fd_set ListeningSocketsList;
- SOCKET maxSocket, sock;
- int i;
- int status;
-
- FD_ZERO(&ListeningSocketsList);
- maxSocket = 0;
-
- for (i = 0; i < numsockets; i++)
- {
- FD_SET(SocketList[i], &ListeningSocketsList);
- if (SocketList[i] > maxSocket) maxSocket = SocketList[i];
- }
-
- status = select(maxSocket + 1, &ListeningSocketsList, NULL, NULL, NULL);
-
- if (status < 0) return INVALID_SOCKET;
-
- sock = INVALID_SOCKET;
-
- for (i = 0; i < numsockets; i++)
- {
- if (FD_ISSET(SocketList[i], &ListeningSocketsList))
- {
- sock = SocketList[i];
- break;
- }
- }
-
- if (sock == INVALID_SOCKET)
- return INVALID_SOCKET;
- else
- return accept(sock, NULL, NULL);
-}
-
-
-void closeAllListeningSockets()
-{
- int i;
-
- for (i = 0; i < numsockets; i++)
- {
- shutdown(SocketList[i], VLMCSD_SHUT_RDWR);
- socketclose(SocketList[i]);
- }
-}
-#endif // NO_SOCKETS
-
-
-static void serveClient(const SOCKET s_client, const DWORD RpcAssocGroup)
-{
-# if !defined(NO_TIMEOUT) && !__minix__
-
-# ifndef _WIN32 // Standard Posix timeout structure
-
- struct timeval to;
- to.tv_sec = ServerTimeout;
- to.tv_usec = 0;
-
- #else // Windows requires a DWORD with milliseconds
-
- DWORD to = ServerTimeout * 1000;
-
-# endif // _WIN32
-
-# if !defined(NO_LOG) && defined(_PEDANTIC)
-
- int result =
- setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to)) ||
- setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
-
- if (result) logger("Warning: Set timeout failed: %s\n", vlmcsd_strerror(socket_errno));
-
-# else // !(!defined(NO_LOG) && defined(_PEDANTIC))
-
- setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to));
- setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
-
-# endif // !(!defined(NO_LOG) && defined(_PEDANTIC))
-
-# endif // !defined(NO_TIMEOUT) && !__minix__
-
- char ipstr[64];
- socklen_t len;
- struct sockaddr_storage addr;
-
- len = sizeof addr;
-
- if (getpeername(s_client, (struct sockaddr*)&addr, &len) ||
- !ip2str(ipstr, sizeof(ipstr), (struct sockaddr*)&addr, len))
- {
-# if !defined(NO_LOG) && defined(_PEDANTIC)
- logger("Fatal: Cannot determine client's IP address: %s\n", vlmcsd_strerror(errno));
-# endif // !defined(NO_LOG) && defined(_PEDANTIC)
- socketclose(s_client);
- return;
- }
-
-
-# ifndef NO_LOG
- const char *const connection_type = addr.ss_family == AF_INET6 ? cIPv6 : cIPv4;
- static const char *const cAccepted = "accepted";
- static const char *const cClosed = "closed";
- static const char *const fIP = "%s connection %s: %s.\n";
-
- logger(fIP, connection_type, cAccepted, ipstr);
- #endif // NO_LOG
-
- rpcServer(s_client, RpcAssocGroup, ipstr);
-
-# ifndef NO_LOG
- logger(fIP, connection_type, cClosed, ipstr);
-# endif // NO_LOG
-
- socketclose(s_client);
-}
-
-
-#ifndef NO_SOCKETS
-static void post_sem(void)
-{
- #if !defined(NO_LIMIT) && !__minix__
- if (!InetdMode && MaxTasks != SEM_VALUE_MAX)
- {
- semaphore_post(Semaphore);
- }
- #endif // !defined(NO_LIMIT) && !__minix__
-}
-
-
-static void wait_sem(void)
-{
- #if !defined(NO_LIMIT) && !__minix__
- if (!InetdMode && MaxTasks != SEM_VALUE_MAX)
- {
- semaphore_wait(Semaphore);
- }
- #endif // !defined(NO_LIMIT) && !__minix__
-}
-#endif // NO_SOCKETS
-
-#if defined(USE_THREADS) && !defined(NO_SOCKETS)
-
-#if defined(_WIN32) || defined(__CYGWIN__) // Win32 Threads
-static DWORD WINAPI serveClientThreadProc(PCLDATA clData)
-#else // Posix threads
-static void *serveClientThreadProc (PCLDATA clData)
-#endif // Thread proc is identical in WIN32 and Posix threads
-{
- serveClient(clData->socket, clData->RpcAssocGroup);
- free(clData);
- post_sem();
-
- return 0;
-}
-
-#endif // USE_THREADS
-
-
-#ifndef NO_SOCKETS
-
-#if defined(USE_THREADS) && (defined(_WIN32) || defined(__CYGWIN__)) // Windows Threads
-static int serveClientAsyncWinThreads(const PCLDATA thr_CLData)
-{
- wait_sem();
-
- HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)serveClientThreadProc, thr_CLData, 0, NULL);
-
- if (h)
- CloseHandle(h);
- else
- {
- socketclose(thr_CLData->socket);
- free(thr_CLData);
- post_sem();
- return GetLastError();
- }
-
- return NO_ERROR;
-}
-#endif // defined(USE_THREADS) && defined(_WIN32) // Windows Threads
-
-
-#if defined(USE_THREADS) && !defined(_WIN32) && !defined(__CYGWIN__) // Posix Threads
-static int ServeClientAsyncPosixThreads(const PCLDATA thr_CLData)
-{
- pthread_t p_thr;
- pthread_attr_t attr;
-
- wait_sem();
-
- // Must set detached state to avoid memory leak
- if (pthread_attr_init(&attr) ||
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) ||
- pthread_create(&p_thr, &attr, (void * (*)(void *))serveClientThreadProc, thr_CLData))
- {
- socketclose(thr_CLData->socket);
- free(thr_CLData);
- post_sem();
- return !0;
- }
-
- return 0;
-}
-#endif // defined(USE_THREADS) && !defined(_WIN32) // Posix Threads
-
-#ifndef USE_THREADS // fork() implementation
-static void ChildSignalHandler(const int signal)
-{
- if (signal == SIGHUP) return;
-
- post_sem();
-
- #ifndef NO_LOG
- logger("Warning: Child killed/crashed by %s\n", strsignal(signal));
- #endif // NO_LOG
-
- exit(!0);
-}
-
-static int ServeClientAsyncFork(const SOCKET s_client, const DWORD RpcAssocGroup)
-{
- int pid;
- wait_sem();
-
- if ((pid = fork()) < 0)
- {
- return errno;
- }
- else if ( pid )
- {
- // Parent process
- socketclose(s_client);
- return 0;
- }
- else
- {
- // Child process
-
- // Setup a Child Handler for most common termination signals
- struct sigaction sa;
-
- sa.sa_flags = 0;
- sa.sa_handler = ChildSignalHandler;
-
- static int signallist[] = { SIGHUP, SIGINT, SIGTERM, SIGSEGV, SIGILL, SIGFPE, SIGBUS };
-
- if (!sigemptyset(&sa.sa_mask))
- {
- uint_fast8_t i;
-
- for (i = 0; i < _countof(signallist); i++)
- {
- sigaction(signallist[i], &sa, NULL);
- }
- }
-
- serveClient(s_client, RpcAssocGroup);
- post_sem();
- exit(0);
- }
-}
-#endif
-
-
-int serveClientAsync(const SOCKET s_client, const DWORD RpcAssocGroup)
-{
- #ifndef USE_THREADS // fork() implementation
-
- return ServeClientAsyncFork(s_client, RpcAssocGroup);
-
- #else // threads implementation
-
- PCLDATA thr_CLData = (PCLDATA)vlmcsd_malloc(sizeof(CLDATA));
- thr_CLData->socket = s_client;
- thr_CLData->RpcAssocGroup = RpcAssocGroup;
-
- #if defined(_WIN32) || defined (__CYGWIN__) // Windows threads
-
- return serveClientAsyncWinThreads(thr_CLData);
-
- #else // Posix Threads
-
- return ServeClientAsyncPosixThreads(thr_CLData);
-
- #endif // Posix Threads
-
- #endif // USE_THREADS
-}
-
-#endif // NO_SOCKETS
-
-
-int runServer()
-{
- DWORD RpcAssocGroup = rand32();
-
- // If compiled for inetd-only mode just serve the stdin socket
- #ifdef NO_SOCKETS
- serveClient(STDIN_FILENO, RpcAssocGroup);
- return 0;
- #else
- // In inetd mode just handle the stdin socket
- if (InetdMode)
- {
- serveClient(STDIN_FILENO, RpcAssocGroup);
- return 0;
- }
-
- // Standalone mode
- for (;;)
- {
- int error;
- SOCKET s_client;
-
- if ( (s_client = network_accept_any()) == INVALID_SOCKET )
- {
- error = socket_errno;
-
- if (error == VLMCSD_EINTR || error == VLMCSD_ECONNABORTED) continue;
-
- #ifdef _NTSERVICE
- if (ServiceShutdown) return 0;
- #endif
-
- #ifndef NO_LOG
- logger("Fatal: %s\n",vlmcsd_strerror(error));
- #endif
-
- return error;
- }
-
- RpcAssocGroup++;
- serveClientAsync(s_client, RpcAssocGroup);
- }
- #endif // NO_SOCKETS
-
- return 0;
-}
-
-#endif // USE_MSRPC
-#ifndef _DEFAULT_SOURCE
-#define _DEFAULT_SOURCE
-#endif // _DEFAULT_SOURCE
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef USE_MSRPC
-
-#include
-#include
-#include
-#include
-#include
-#include
-#if !defined(_WIN32)
-#include
-#include
-#endif
-#include "rpc.h"
-#include "output.h"
-#include "crypto.h"
-#include "endian.h"
-#include "helpers.h"
-#include "network.h"
-#include "shared_globals.h"
-
-/* Forwards */
-
-static int checkRpcHeader(const RPC_HEADER *const Header, const BYTE desiredPacketType, const PRINTFUNC p);
-
-
-/* Data definitions */
-
-// All GUIDs are defined as BYTE[16] here. No big-endian/little-endian byteswapping required.
-static const BYTE TransferSyntaxNDR32[] = {
- 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C, 0xC9, 0x11, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60
-};
-
-static const BYTE InterfaceUuid[] = {
- 0x75, 0x21, 0xc8, 0x51, 0x4e, 0x84, 0x50, 0x47, 0xB0, 0xD8, 0xEC, 0x25, 0x55, 0x55, 0xBC, 0x06
-};
-
-static const BYTE TransferSyntaxNDR64[] = {
- 0x33, 0x05, 0x71, 0x71, 0xba, 0xbe, 0x37, 0x49, 0x83, 0x19, 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36
-};
-
-static const BYTE BindTimeFeatureNegotiation[] = {
- 0x2c, 0x1c, 0xb7, 0x6c, 0x12, 0x98, 0x40, 0x45, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-
-//
-// Dispatch RPC payload to kms.c
-//
-typedef int (*CreateResponse_t)(const void *const, void *const, const char* const);
-
-static const struct {
- unsigned int RequestSize;
- CreateResponse_t CreateResponse;
-} _Versions[] = {
- { sizeof(REQUEST_V4), (CreateResponse_t) CreateResponseV4 },
- { sizeof(REQUEST_V6), (CreateResponse_t) CreateResponseV6 },
- { sizeof(REQUEST_V6), (CreateResponse_t) CreateResponseV6 }
-};
-
-RPC_FLAGS RpcFlags;
-static int_fast8_t firstPacketSent;
-
-//
-// RPC request (server)
-//
-#if defined(_PEDANTIC) && !defined(NO_LOG)
-static void CheckRpcRequest(const RPC_REQUEST64 *const Request, const unsigned int len, WORD* NdrCtx, WORD* Ndr64Ctx, WORD Ctx)
-{
- uint_fast8_t kmsMajorVersion;
- uint32_t requestSize = Ctx != *Ndr64Ctx ? sizeof(RPC_REQUEST) : sizeof(RPC_REQUEST64);
-
- if (len < requestSize)
- {
- logger("Fatal: RPC request (including header) must be at least %i bytes but is only %i bytes.\n",
- (int)(sizeof(RPC_HEADER) + requestSize),
- (int)(len + sizeof(RPC_HEADER))
- );
-
- return;
- }
-
- if (len < requestSize + sizeof(DWORD))
- {
- logger("Fatal: KMS Request too small to contain version info (less than 4 bytes).\n");
- return;
- }
-
- if (Ctx != *Ndr64Ctx)
- kmsMajorVersion = LE16(((WORD*)Request->Ndr.Data)[1]);
- else
- kmsMajorVersion = LE16(((WORD*)Request->Ndr64.Data)[1]);
-
- if (kmsMajorVersion > 6)
- {
- logger("Fatal: KMSv%u is not supported.\n", (unsigned int)kmsMajorVersion);
- }
- else
- {
- if (len >_Versions[kmsMajorVersion].RequestSize + requestSize)
- logger("Warning: %u excess bytes in RPC request.\n",
- len - _Versions[kmsMajorVersion].RequestSize
- );
- }
-
- if (Ctx != *Ndr64Ctx && Ctx != *NdrCtx)
- logger("Warning: Context id should be %u (NDR32) or %u (NDR64) but is %u.\n",
- (unsigned int)*NdrCtx,
- (unsigned int)*Ndr64Ctx,
- Ctx
- );
-
- if (Request->Opnum)
- logger("Warning: OpNum should be 0 but is %u.\n",
- (unsigned int)LE16(Request->Opnum)
- );
-
- if (LE32(Request->AllocHint) != len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr))
- logger("Warning: Allocation hint should be %u but is %u.\n",
- len + sizeof(Request->Ndr),
- LE32(Request->AllocHint)
- );
-
- if (Ctx != *Ndr64Ctx)
- {
- if (LE32(Request->Ndr.DataLength) != len - sizeof(RPC_REQUEST))
- logger("Warning: NDR32 data length field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST),
- LE32(Request->Ndr.DataLength)
- );
-
- if (LE32(Request->Ndr.DataSizeIs) != len - sizeof(RPC_REQUEST))
- logger("Warning: NDR32 data size field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST),
- LE32(Request->Ndr.DataSizeIs)
- );
- }
- else
- {
- if (LE64(Request->Ndr64.DataLength) != len - sizeof(RPC_REQUEST64))
- logger("Warning: NDR32 data length field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr),
- LE64(Request->Ndr64.DataLength)
- );
-
- if (LE64(Request->Ndr64.DataSizeIs) != len - sizeof(RPC_REQUEST64))
- logger("Warning: NDR32 data size field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST64),
- LE64(Request->Ndr64.DataSizeIs)
- );
- }
-}
-#endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
-/*
- * check RPC request for (somewhat) correct size
- * allow any size that does not cause CreateResponse to fail badly
- */
-static unsigned int checkRpcRequestSize(const RPC_REQUEST64 *const Request, const unsigned int requestSize, WORD* NdrCtx, WORD* Ndr64Ctx)
-{
- WORD Ctx = LE16(Request->ContextId);
-
-# if defined(_PEDANTIC) && !defined(NO_LOG)
- CheckRpcRequest(Request, requestSize, NdrCtx, Ndr64Ctx, Ctx);
-# endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
- // Anything that is smaller than a v4 request is illegal
- if (requestSize < sizeof(REQUEST_V4) + (Ctx != *Ndr64Ctx ? sizeof(RPC_REQUEST) : sizeof(RPC_REQUEST64))) return 0;
-
- // Get KMS major version
- uint_fast16_t _v;
-
- if (Ctx != *Ndr64Ctx)
- _v = LE16(((WORD*)Request->Ndr.Data)[1]) - 4;
- else
- _v = LE16(((WORD*)Request->Ndr64.Data)[1]) - 4;
-
- // Only KMS v4, v5 and v6 are supported
- if (_v >= vlmcsd_countof(_Versions))
- {
-# ifndef NO_LOG
- logger("Fatal: KMSv%i unsupported\n", _v + 4);
-# endif // NO_LOG
- return 0;
- }
-
- // Could check for equality but allow bigger requests to support buggy RPC clients (e.g. wine)
- // Buffer overrun is check by caller.
- return (requestSize >= _Versions[_v].RequestSize);
-}
-
-
-/*
- * Handles the actual KMS request from the client.
- * Calls KMS functions (CreateResponseV4 or CreateResponseV6) in kms.c
- * Returns size of the KMS response packet or 0 on failure.
- *
- * The RPC packet size (excluding header) is actually in Response->AllocHint
- */
-static int rpcRequest(const RPC_REQUEST64 *const Request, RPC_RESPONSE64 *const Response, const DWORD RpcAssocGroup_unused, const SOCKET sock_unused, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr)
-{
- uint_fast16_t _v;
- int ResponseSize;
- WORD Ctx = LE16(Request->ContextId);
- BYTE* requestData;
- BYTE* responseData;
- BYTE* pRpcReturnCode;
- int len;
-
- if (Ctx != *Ndr64Ctx)
- {
- requestData = (BYTE*)&Request->Ndr.Data;
- responseData = (BYTE*)&Response->Ndr.Data;
- }
- else
- {
- requestData = (BYTE*)&Request->Ndr64.Data;
- responseData = (BYTE*)&Response->Ndr64.Data;
- }
-
- _v = LE16(((WORD*)requestData)[1]) - 4;
-
- if (!(ResponseSize = _Versions[_v].CreateResponse(requestData, responseData, ipstr)))
- {
- return 0;
- }
-
- if (Ctx != *Ndr64Ctx)
- {
- Response->Ndr.DataSizeMax = LE32(0x00020000);
- Response->Ndr.DataLength = Response->Ndr.DataSizeIs = LE32(ResponseSize);
- len = ResponseSize + sizeof(Response->Ndr);
- }
- else
- {
- Response->Ndr64.DataSizeMax = LE64(0x00020000ULL);
- Response->Ndr64.DataLength = Response->Ndr64.DataSizeIs = LE64((uint64_t)ResponseSize);
- len = ResponseSize + sizeof(Response->Ndr64);
- }
-
- pRpcReturnCode = ((BYTE*)&Response->Ndr) + len;
- UA32(pRpcReturnCode) = 0; //LE32 not needed for 0
- len += sizeof(DWORD);
-
- // Pad zeros to 32-bit align (seems not neccassary but Windows RPC does it this way)
- int pad = ((~len & 3) + 1) & 3;
- memset(pRpcReturnCode + sizeof(DWORD), 0, pad);
- len += pad;
-
- Response->AllocHint = LE32(len);
- Response->ContextId = Request->ContextId;
-
- *((WORD*)&Response->CancelCount) = 0; // CancelCount + Pad1
-
- return len + 8;
-}
-
-
-#if defined(_PEDANTIC) && !defined(NO_LOG)
-static void CheckRpcBindRequest(const RPC_BIND_REQUEST *const Request, const unsigned int len)
-{
- uint_fast8_t i, HasTransferSyntaxNDR32 = FALSE;
- char guidBuffer1[GUID_STRING_LENGTH + 1], guidBuffer2[GUID_STRING_LENGTH + 1];
-
- uint32_t CapCtxItems = (len - sizeof(*Request) + sizeof(Request->CtxItems)) / sizeof(Request->CtxItems);
- DWORD NumCtxItems = LE32(Request->NumCtxItems);
-
- if (NumCtxItems < CapCtxItems) // Can't be too small because already handled by RpcBindSize
- logger("Warning: Excess bytes in RPC bind request.\n");
-
- for (i = 0; i < NumCtxItems; i++)
- {
- if (!IsEqualGUID(&Request->CtxItems[i].InterfaceUUID, InterfaceUuid))
- {
- uuid2StringLE((GUID*)&Request->CtxItems[i].InterfaceUUID, guidBuffer1);
- uuid2StringLE((GUID*)InterfaceUuid, guidBuffer2);
- logger("Warning: Interface UUID is %s but should be %s in Ctx item %u.\n", guidBuffer1, guidBuffer2, (unsigned int)i);
- }
-
- if (Request->CtxItems[i].NumTransItems != LE16(1))
- logger("Fatal: %u NDR32 transfer items detected in Ctx item %u, but only one is supported.\n",
- (unsigned int)LE16(Request->CtxItems[i].NumTransItems), (unsigned int)i
- );
-
- if (Request->CtxItems[i].InterfaceVerMajor != LE16(1) || Request->CtxItems[i].InterfaceVerMinor != 0)
- logger("Warning: NDR32 Interface version is %u.%u but should be 1.0.\n",
- (unsigned int)LE16(Request->CtxItems[i].InterfaceVerMajor),
- (unsigned int)LE16(Request->CtxItems[i].InterfaceVerMinor)
- );
-
- if (Request->CtxItems[i].ContextId != LE16((WORD)i))
- logger("Warning: context id of Ctx item %u is %u.\n", (unsigned int)i, (unsigned int)Request->CtxItems[i].ContextId);
-
- if ( IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
- {
- HasTransferSyntaxNDR32 = TRUE;
-
- if (Request->CtxItems[i].SyntaxVersion != LE32(2))
- logger("NDR32 transfer syntax version is %u but should be 2.\n", LE32(Request->CtxItems[i].SyntaxVersion));
- }
- else if ( IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
- {
- if (Request->CtxItems[i].SyntaxVersion != LE32(1))
- logger("NDR64 transfer syntax version is %u but should be 1.\n", LE32(Request->CtxItems[i].SyntaxVersion));
- }
- else if (!memcmp(BindTimeFeatureNegotiation, (BYTE*)(&Request->CtxItems[i].TransferSyntax), 8))
- {
- if (Request->CtxItems[i].SyntaxVersion != LE32(1))
- logger("BTFN syntax version is %u but should be 1.\n", LE32(Request->CtxItems[i].SyntaxVersion));
- }
- }
-
- if (!HasTransferSyntaxNDR32)
- logger("Warning: RPC bind request has no NDR32 CtxItem.\n");
-}
-#endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
-
-/*
- * Check, if we receive enough bytes to return a valid RPC bind response
- */
-static unsigned int checkRpcBindSize(const RPC_BIND_REQUEST *const Request, const unsigned int RequestSize, WORD* NdrCtx, WORD* Ndr64Ctx)
-{
- if ( RequestSize < sizeof(RPC_BIND_REQUEST) ) return FALSE;
-
- unsigned int _NumCtxItems = LE32(Request->NumCtxItems);
-
- if ( RequestSize < sizeof(RPC_BIND_REQUEST) - sizeof(Request->CtxItems[0]) + _NumCtxItems * sizeof(Request->CtxItems[0]) ) return FALSE;
-
- #if defined(_PEDANTIC) && !defined(NO_LOG)
- CheckRpcBindRequest(Request, RequestSize);
- #endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
- return TRUE;
-}
-
-
-/*
- * Accepts a bind or alter context request from the client and composes the bind response.
- * Needs the socket because the tcp port number is part of the response.
- * len is not used here.
- *
- * Returns TRUE on success.
- */
-static int rpcBind(const RPC_BIND_REQUEST *const Request, RPC_BIND_RESPONSE* Response, const DWORD RpcAssocGroup, const SOCKET sock, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr_unused)
-{
- unsigned int i, _st = FALSE;
- DWORD numCtxItems = LE32(Request->NumCtxItems);
- int_fast8_t IsNDR64possible = FALSE;
- uint_fast8_t portNumberSize;
-
- socklen_t socklen;
- struct sockaddr_storage addr;
-
- // M$ RPC does not do this. Pad bytes contain apparently random data
- // memset(Response->SecondaryAddress, 0, sizeof(Response->SecondaryAddress));
-
- socklen = sizeof addr;
-
- if (
- packetType == RPC_PT_ALTERCONTEXT_REQ ||
- getsockname(sock, (struct sockaddr*)&addr, &socklen) ||
- getnameinfo((struct sockaddr*)&addr, socklen, NULL, 0, (char*)Response->SecondaryAddress, sizeof(Response->SecondaryAddress), NI_NUMERICSERV))
- {
- portNumberSize = Response->SecondaryAddressLength = 0;
- }
- else
- {
- portNumberSize = strlen((char*)Response->SecondaryAddress) + 1;
- Response->SecondaryAddressLength = LE16(portNumberSize);
- }
-
- Response->MaxXmitFrag = Request->MaxXmitFrag;
- Response->MaxRecvFrag = Request->MaxRecvFrag;
- Response->AssocGroup = LE32(RpcAssocGroup);
-
- // This is really ugly (but efficient) code to support padding after the secondary address field
- if (portNumberSize < 3)
- {
- Response = (RPC_BIND_RESPONSE*)((BYTE*)Response - 4);
- }
-
- Response->NumResults = Request->NumCtxItems;
-
- if (UseRpcNDR64)
- {
- for (i = 0; i < numCtxItems; i++)
- {
- if ( IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
- {
- /*if (packetType == RPC_PT_BIND_REQ)*/
- *NdrCtx = LE16(Request->CtxItems[i].ContextId);
- }
-
- if ( IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
- {
- IsNDR64possible = TRUE;
-
- /*if (packetType == RPC_PT_BIND_REQ)*/
- *Ndr64Ctx = LE16(Request->CtxItems[i].ContextId);
- }
- }
- }
-
- for (i = 0; i < numCtxItems; i++)
- {
- memset(&Response->Results[i].TransferSyntax, 0, sizeof(GUID));
-
- if ( !IsNDR64possible && IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
- {
- Response->Results[i].SyntaxVersion = LE32(2);
- Response->Results[i].AckResult =
- Response->Results[i].AckReason = RPC_BIND_ACCEPT;
- memcpy(&Response->Results[i].TransferSyntax, TransferSyntaxNDR32, sizeof(GUID));
-
- _st = TRUE;
- }
- else if ( IsNDR64possible && IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
- {
- Response->Results[i].SyntaxVersion = LE32(1);
- Response->Results[i].AckResult =
- Response->Results[i].AckReason = RPC_BIND_ACCEPT;
- memcpy(&Response->Results[i].TransferSyntax, TransferSyntaxNDR64, sizeof(GUID));
-
- _st = TRUE;
- }
- else if ( UseRpcBTFN && !memcmp(BindTimeFeatureNegotiation, (BYTE*)(&Request->CtxItems[i].TransferSyntax), 8) )
- {
- Response->Results[i].SyntaxVersion = 0;
- Response->Results[i].AckResult = RPC_BIND_ACK;
-
- // Features requested are actually encoded in the GUID
- Response->Results[i].AckReason =
- ((WORD*)(&Request->CtxItems[i].TransferSyntax))[4] &
- (RPC_BTFN_SEC_CONTEXT_MULTIPLEX | RPC_BTFN_KEEP_ORPHAN);
- }
- else
- {
- Response->Results[i].SyntaxVersion = 0;
- Response->Results[i].AckResult =
- Response->Results[i].AckReason = RPC_BIND_NACK; // Unsupported
- }
- }
-
- if ( !_st ) return 0;
-
- return sizeof(RPC_BIND_RESPONSE) + numCtxItems * sizeof(((RPC_BIND_RESPONSE *)0)->Results[0]) - (portNumberSize < 3 ? 4 : 0);
-}
-
-
-//
-// Main RPC handling routine
-//
-typedef unsigned int (*GetResponseSize_t)(const void *const request, const unsigned int requestSize, WORD* NdrCtx, WORD* Ndr64Ctx);
-typedef int (*GetResponse_t)(const void* const request, void* response, const DWORD rpcAssocGroup, const SOCKET socket, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr);
-
-static const struct {
- BYTE ResponsePacketType;
- GetResponseSize_t CheckRequestSize;
- GetResponse_t GetResponse;
-}
-_Actions[] = {
- { RPC_PT_BIND_ACK, (GetResponseSize_t)checkRpcBindSize, (GetResponse_t) rpcBind },
- { RPC_PT_RESPONSE, (GetResponseSize_t)checkRpcRequestSize, (GetResponse_t) rpcRequest },
- { RPC_PT_ALTERCONTEXT_ACK, (GetResponseSize_t)checkRpcBindSize, (GetResponse_t) rpcBind },
-};
-
-
-/*
- * This is the main RPC server loop. Returns after KMS request has been serviced
- * or a timeout has occured.
- */
-void rpcServer(const SOCKET sock, const DWORD RpcAssocGroup, const char* const ipstr)
-{
- RPC_HEADER rpcRequestHeader;
- WORD NdrCtx = INVALID_NDR_CTX, Ndr64Ctx = INVALID_NDR_CTX;
-
- randomNumberInit();
-
- while (_recv(sock, &rpcRequestHeader, sizeof(rpcRequestHeader)))
- {
- //int_fast8_t _st;
- unsigned int request_len, response_len;
- uint_fast8_t _a;
-
- #if defined(_PEDANTIC) && !defined(NO_LOG)
- checkRpcHeader(&rpcRequestHeader, rpcRequestHeader.PacketType, &logger);
- #endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
- switch (rpcRequestHeader.PacketType)
- {
- case RPC_PT_BIND_REQ: _a = 0; break;
- case RPC_PT_REQUEST: _a = 1; break;
- case RPC_PT_ALTERCONTEXT_REQ: _a = 2; break;
- default: return;
- }
-
- request_len = LE16(rpcRequestHeader.FragLength) - sizeof(rpcRequestHeader);
-
- BYTE requestBuffer[MAX_REQUEST_SIZE + sizeof(RPC_RESPONSE64)];
- BYTE responseBuffer[MAX_RESPONSE_SIZE + sizeof(RPC_HEADER) + sizeof(RPC_RESPONSE64)];
-
- RPC_HEADER *rpcResponseHeader = (RPC_HEADER *)responseBuffer;
- RPC_RESPONSE* rpcResponse = (RPC_RESPONSE*)(responseBuffer + sizeof(rpcRequestHeader));
-
- // The request is larger than the buffer size
- if (request_len > MAX_REQUEST_SIZE + sizeof(RPC_REQUEST64)) return;
-
- // Unable to receive the complete request
- if (!_recv(sock, requestBuffer, request_len)) return;
-
- // Request is invalid
- if (!_Actions[_a].CheckRequestSize(requestBuffer, request_len, &NdrCtx, &Ndr64Ctx)) return;
-
- // Unable to create a valid response from request
- if (!(response_len = _Actions[_a].GetResponse(requestBuffer, rpcResponse, RpcAssocGroup, sock, &NdrCtx, &Ndr64Ctx, rpcRequestHeader.PacketType, ipstr))) return;
-
- response_len += sizeof(RPC_HEADER);
-
- memcpy(rpcResponseHeader, &rpcRequestHeader, sizeof(RPC_HEADER));
-
- rpcResponseHeader->FragLength = LE16(response_len);
- rpcResponseHeader->PacketType = _Actions[_a].ResponsePacketType;
-
- if (rpcResponseHeader->PacketType == RPC_PT_ALTERCONTEXT_ACK)
- rpcResponseHeader->PacketFlags = RPC_PF_FIRST | RPC_PF_LAST;
-
- if (!_send(sock, responseBuffer, response_len)) return;
-
- if (DisconnectImmediately && rpcResponseHeader->PacketType == RPC_PT_RESPONSE)
- shutdown(sock, VLMCSD_SHUT_RDWR);
- }
-}
-
-
-/* RPC client functions */
-
-static DWORD CallId = 2; // M$ starts with CallId 2. So we do the same.
-
-
-/*
- * Checks RPC header. Returns 0 on success.
- * This is mainly for debugging a non Microsoft KMS server that uses its own RPC code.
- */
-static int checkRpcHeader(const RPC_HEADER *const Header, const BYTE desiredPacketType, const PRINTFUNC p)
-{
- int status = 0;
-
- if (Header->PacketType != desiredPacketType)
- {
- p("Fatal: Received wrong RPC packet type. Expected %u but got %u\n",
- (uint32_t)desiredPacketType,
- Header->PacketType
- );
- status = !0;
- }
-
- if (Header->DataRepresentation != BE32(0x10000000))
- {
- p("Fatal: RPC response does not conform to Microsoft's limited support of DCE RPC\n");
- status = !0;
- }
-
- if (Header->AuthLength != 0)
- {
- p("Fatal: RPC response requests authentication\n");
- status = !0;
- }
-
- // vlmcsd does not support fragmented packets (not yet neccassary)
- if ( (Header->PacketFlags & (RPC_PF_FIRST | RPC_PF_LAST)) != (RPC_PF_FIRST | RPC_PF_LAST) )
- {
- p("Fatal: RPC packet flags RPC_PF_FIRST and RPC_PF_LAST are not both set.\n");
- status = !0;
- }
-
- if (Header->PacketFlags & RPC_PF_CANCEL_PENDING) p("Warning: %s should not be set\n", "RPC_PF_CANCEL_PENDING");
- if (Header->PacketFlags & RPC_PF_RESERVED) p("Warning: %s should not be set\n", "RPC_PF_RESERVED");
- if (Header->PacketFlags & RPC_PF_NOT_EXEC) p("Warning: %s should not be set\n", "RPC_PF_NOT_EXEC");
- if (Header->PacketFlags & RPC_PF_MAYBE) p("Warning: %s should not be set\n", "RPC_PF_MAYBE");
- if (Header->PacketFlags & RPC_PF_OBJECT) p("Warning: %s should not be set\n", "RPC_PF_OBJECT");
-
- if (Header->VersionMajor != 5 || Header->VersionMinor != 0)
- {
- p("Fatal: Expected RPC version 5.0 and got %u.%u\n", Header->VersionMajor, Header->VersionMinor);
- status = !0;
- }
-
- return status;
-}
-
-
-/*
- * Checks an RPC response header. Does basic header checks by calling checkRpcHeader()
- * and then does additional checks if response header complies with the respective request header.
- * PRINTFUNC p can be anything that has the same prototype as printf.
- * Returns 0 on success.
- */
-static int checkRpcResponseHeader(const RPC_HEADER *const ResponseHeader, const RPC_HEADER *const RequestHeader, const BYTE desiredPacketType, const PRINTFUNC p)
-{
- static int_fast8_t WineBugDetected = FALSE;
- int status = checkRpcHeader(ResponseHeader, desiredPacketType, p);
-
- if (desiredPacketType == RPC_PT_BIND_ACK)
- {
- if ((ResponseHeader->PacketFlags & RPC_PF_MULTIPLEX) != (RequestHeader->PacketFlags & RPC_PF_MULTIPLEX))
- {
- p("Warning: RPC_PF_MULTIPLEX of RPC request and response should match\n");
- }
- }
- else
- {
- if (ResponseHeader->PacketFlags & RPC_PF_MULTIPLEX)
- {
- p("Warning: %s should not be set\n", "RPC_PF_MULTIPLEX");
- }
- }
-
- if (!status && ResponseHeader->CallId == LE32(1))
- {
- if (!WineBugDetected)
- {
- p("Warning: Buggy RPC of Wine detected. Call Id of Response is always 1\n");
- WineBugDetected = TRUE;
- }
- }
- else if (ResponseHeader->CallId != RequestHeader->CallId)
- {
- p("Fatal: Sent Call Id %u but received answer for Call Id %u\n",
- (uint32_t)LE32(RequestHeader->CallId),
- (uint32_t)LE32(ResponseHeader->CallId)
- );
-
- status = !0;
- }
-
- return status;
-}
-
-/*
- * Initializes an RPC request header as needed for KMS, i.e. packet always fits in one fragment.
- * size cannot be greater than fragment length negotiated during RPC bind.
- */
-static void createRpcRequestHeader(RPC_HEADER* RequestHeader, BYTE packetType, WORD size)
-{
- RequestHeader->PacketType = packetType;
- RequestHeader->PacketFlags = RPC_PF_FIRST | RPC_PF_LAST;
- RequestHeader->VersionMajor = 5;
- RequestHeader->VersionMinor = 0;
- RequestHeader->AuthLength = 0;
- RequestHeader->DataRepresentation = BE32(0x10000000); // Little endian, ASCII charset, IEEE floating point
- RequestHeader->CallId = LE32(CallId);
- RequestHeader->FragLength = LE16(size);
-}
-
-
-/*
- * Sends a KMS request via RPC and receives a response.
- * Parameters are raw (encrypted) reqeuests / responses.
- * Returns 0 on success.
- */
-RpcStatus rpcSendRequest(const RpcCtx sock, const BYTE *const KmsRequest, const size_t requestSize, BYTE **KmsResponse, size_t *const responseSize)
-{
- #define MAX_EXCESS_BYTES 16
- RPC_HEADER *RequestHeader, ResponseHeader;
- RPC_REQUEST64 *RpcRequest;
- RPC_RESPONSE64 _Response;
- int status = 0;
- int_fast8_t useNdr64 = UseRpcNDR64 && firstPacketSent;
- size_t size = sizeof(RPC_HEADER) + (useNdr64 ? sizeof(RPC_REQUEST64) : sizeof(RPC_REQUEST)) + requestSize;
- size_t responseSize2;
-
- *KmsResponse = NULL;
-
- BYTE *_Request = (BYTE*)vlmcsd_malloc(size);
-
- RequestHeader = (RPC_HEADER*)_Request;
- RpcRequest = (RPC_REQUEST64*)(_Request + sizeof(RPC_HEADER));
-
- createRpcRequestHeader(RequestHeader, RPC_PT_REQUEST, size);
-
- // Increment CallId for next Request
- CallId++;
-
- RpcRequest->Opnum = 0;
-
- if (useNdr64)
- {
- RpcRequest->ContextId = LE16(1); // We negotiate NDR64 always as context 1
- RpcRequest->AllocHint = LE32(requestSize + sizeof(RpcRequest->Ndr64));
- RpcRequest->Ndr64.DataLength = LE64((uint64_t)requestSize);
- RpcRequest->Ndr64.DataSizeIs = LE64((uint64_t)requestSize);
- memcpy(RpcRequest->Ndr64.Data, KmsRequest, requestSize);
- }
- else
- {
- RpcRequest->ContextId = 0; // We negotiate NDR32 always as context 0
- RpcRequest->AllocHint = LE32(requestSize + sizeof(RpcRequest->Ndr));
- RpcRequest->Ndr.DataLength = LE32(requestSize);
- RpcRequest->Ndr.DataSizeIs = LE32(requestSize);
- memcpy(RpcRequest->Ndr.Data, KmsRequest, requestSize);
- }
-
- for(;;)
- {
- int bytesread;
-
- if (!_send(sock, _Request, size))
- {
- errorout("\nFatal: Could not send RPC request\n");
- status = !0;
- break;
- }
-
- if (!_recv(sock, &ResponseHeader, sizeof(RPC_HEADER)))
- {
- errorout("\nFatal: No RPC response received from server\n");
- status = !0;
- break;
- }
-
- if ((status = checkRpcResponseHeader(&ResponseHeader, RequestHeader, RPC_PT_RESPONSE, &errorout))) break;
-
- size = useNdr64 ? sizeof(RPC_RESPONSE64) : sizeof(RPC_RESPONSE);
-
- if (size > LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader))
- size = LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader);
-
- if (!_recv(sock, &_Response, size))
- {
- errorout("\nFatal: RPC response is incomplete\n");
- status = !0;
- break;
- }
-
- if (_Response.CancelCount != 0)
- {
- errorout("\nFatal: RPC response cancel count is not 0\n");
- status = !0;
- }
-
- if (_Response.ContextId != (useNdr64 ? LE16(1) : 0))
- {
- errorout("\nFatal: RPC response context id %u is not bound\n", (unsigned int)LE16(_Response.ContextId));
- status = !0;
- }
-
- int_fast8_t sizesMatch;
-
- if (useNdr64)
- {
- *responseSize = (size_t)LE64(_Response.Ndr64.DataLength);
- responseSize2 = (size_t)LE64(_Response.Ndr64.DataSizeIs);
-
- if (!*responseSize || !_Response.Ndr64.DataSizeMax)
- {
- status = (int)LE32(_Response.Ndr64.status);
- break;
- }
-
- sizesMatch = (size_t)LE64(_Response.Ndr64.DataLength) == responseSize2;
- }
- else
- {
- *responseSize = (size_t)LE32(_Response.Ndr.DataLength);
- responseSize2 = (size_t)LE32(_Response.Ndr.DataSizeIs);
-
- if (!*responseSize || !_Response.Ndr.DataSizeMax)
- {
- status = (int)LE32(_Response.Ndr.status);
- break;
- }
-
- sizesMatch = (size_t)LE32(_Response.Ndr.DataLength) == responseSize2;
- }
-
- if (!sizesMatch)
- {
- errorout("\nFatal: NDR data length (%u) does not match NDR data size (%u)\n",
- (uint32_t)*responseSize,
- (uint32_t)LE32(_Response.Ndr.DataSizeIs)
- );
-
- status = !0;
- }
-
- *KmsResponse = (BYTE*)vlmcsd_malloc(*responseSize + MAX_EXCESS_BYTES);
-
- // If RPC stub is too short, assume missing bytes are zero (same ill behavior as MS RPC)
- memset(*KmsResponse, 0, *responseSize + MAX_EXCESS_BYTES);
-
- // Read up to 16 bytes more than bytes expected to detect faulty KMS emulators
- if ((bytesread = recv(sock, (char*)*KmsResponse, *responseSize + MAX_EXCESS_BYTES, 0)) < (int)*responseSize)
- {
- errorout("\nFatal: No or incomplete KMS response received. Required %u bytes but only got %i\n",
- (uint32_t)*responseSize,
- (int32_t)(bytesread < 0 ? 0 : bytesread)
- );
-
- status = !0;
- break;
- }
-
- DWORD *pReturnCode;
-
- size_t len = *responseSize + (useNdr64 ? sizeof(_Response.Ndr64) : sizeof(_Response.Ndr)) + sizeof(*pReturnCode);
- size_t pad = ((~len & 3) + 1) & 3;
-
- if (len + pad != LE32(_Response.AllocHint))
- {
- errorout("\nWarning: RPC stub size is %u, should be %u (probably incorrect padding)\n", (uint32_t)LE32(_Response.AllocHint), (uint32_t)(len + pad));
- }
- else
- {
- size_t i;
- for (i = 0; i < pad; i++)
- {
- if (*(*KmsResponse + *responseSize + sizeof(*pReturnCode) + i))
- {
- errorout("\nWarning: RPC stub data not padded to zeros according to Microsoft standard\n");
- break;
- }
- }
- }
-
- pReturnCode = (DWORD*)(*KmsResponse + *responseSize + pad);
- status = LE32(UA32(pReturnCode));
-
- if (status) errorout("\nWarning: RPC stub data reported Error %u\n", (uint32_t)status);
-
- break;
- }
-
- free(_Request);
- firstPacketSent = TRUE;
- return status;
- #undef MAX_EXCESS_BYTES
-}
-
-
-static int_fast8_t IsNullGuid(BYTE* guidPtr)
-{
- int_fast8_t i;
-
- for (i = 0; i < 16; i++)
- {
- if (guidPtr[i]) return FALSE;
- }
-
- return TRUE;
-}
-
-/*
- * Perform RPC client bind. Accepts a connected client socket.
- * Returns 0 on success. RPC binding is required before any payload can be
- * exchanged. It negotiates about protocol details.
- */
-RpcStatus rpcBindOrAlterClientContext(const RpcCtx sock, BYTE packetType, const int_fast8_t verbose)
-{
- RPC_HEADER *RequestHeader, ResponseHeader;
- RPC_BIND_REQUEST *bindRequest;
- RPC_BIND_RESPONSE *bindResponse;
- int status;
- WORD ctxItems = 1 + (packetType == RPC_PT_BIND_REQ ? UseRpcNDR64 + UseRpcBTFN : 0);
- size_t rpcBindSize = (sizeof(RPC_HEADER) + sizeof(RPC_BIND_REQUEST) + (ctxItems - 1) * sizeof(bindRequest->CtxItems[0]));
- WORD ctxIndex = 0;
- WORD i;
- WORD CtxBTFN = (WORD)~0, CtxNDR64 = (WORD)~0;
- BYTE _Request[rpcBindSize];
-
- RequestHeader = (RPC_HEADER*)_Request;
- bindRequest = (RPC_BIND_REQUEST* )(_Request + sizeof(RPC_HEADER));
-
- createRpcRequestHeader(RequestHeader, packetType, rpcBindSize);
- RequestHeader->PacketFlags |= UseMultiplexedRpc ? RPC_PF_MULTIPLEX : 0;
-
- bindRequest->AssocGroup = 0;
- bindRequest->MaxRecvFrag = bindRequest->MaxXmitFrag = LE16(5840);
- bindRequest->NumCtxItems = LE32(ctxItems);
-
- // data that is identical in all Ctx items
- for (i = 0; i < ctxItems; i++)
- {
- bindRequest->CtxItems[i].ContextId = LE16(i);
- bindRequest->CtxItems[i].InterfaceVerMajor = LE16(1);
- bindRequest->CtxItems[i].InterfaceVerMinor = 0;
- bindRequest->CtxItems[i].NumTransItems = LE16(1);
- bindRequest->CtxItems[i].SyntaxVersion = i ? LE32(1) : LE32(2);
-
- memcpy(&bindRequest->CtxItems[i].InterfaceUUID, InterfaceUuid, sizeof(GUID));
- }
-
- memcpy(&bindRequest->CtxItems[0].TransferSyntax, TransferSyntaxNDR32, sizeof(GUID));
-
- if (UseRpcNDR64 && packetType == RPC_PT_BIND_REQ)
- {
- memcpy(&bindRequest->CtxItems[++ctxIndex].TransferSyntax, TransferSyntaxNDR64, sizeof(GUID));
- CtxNDR64 = ctxIndex;
- }
-
- if (UseRpcBTFN && packetType == RPC_PT_BIND_REQ)
- {
- memcpy(&bindRequest->CtxItems[++ctxIndex].TransferSyntax, BindTimeFeatureNegotiation, sizeof(GUID));
- CtxBTFN = ctxIndex;
- }
-
- if (!_send(sock, _Request, rpcBindSize))
- {
- errorout("\nFatal: Sending RPC bind request failed\n");
- return !0;
- }
-
- if (!_recv(sock, &ResponseHeader, sizeof(RPC_HEADER)))
- {
- errorout("\nFatal: Did not receive a response from server\n");
- return !0;
- }
-
- if ((status = checkRpcResponseHeader
- (
- &ResponseHeader,
- RequestHeader,
- packetType == RPC_PT_BIND_REQ ? RPC_PT_BIND_ACK : RPC_PT_ALTERCONTEXT_ACK,
- &errorout
- )))
- {
- return status;
- }
-
- bindResponse = (RPC_BIND_RESPONSE*)vlmcsd_malloc(LE16(ResponseHeader.FragLength) - sizeof(RPC_HEADER));
- BYTE* bindResponseBytePtr = (BYTE*)bindResponse;
-
- if (!_recv(sock, bindResponse, LE16(ResponseHeader.FragLength) - sizeof(RPC_HEADER)))
- {
- errorout("\nFatal: Incomplete RPC bind acknowledgement received\n");
- free(bindResponseBytePtr);
- return !0;
- }
- else
- {
- /*
- * checking, whether a bind or alter context response is as expected.
- * This check is very strict and checks whether a KMS emulator behaves exactly the same way
- * as Microsoft's RPC does.
- */
- status = 0;
-
- if (bindResponse->SecondaryAddressLength < LE16(3))
- bindResponse = (RPC_BIND_RESPONSE*)(bindResponseBytePtr - 4);
-
- if (bindResponse->NumResults != bindRequest->NumCtxItems)
- {
- errorout("\nFatal: Expected %u CTX items but got %u\n",
- (uint32_t)LE32(bindRequest->NumCtxItems),
- (uint32_t)LE32(bindResponse->NumResults)
- );
-
- status = !0;
- }
-
- for (i = 0; i < ctxItems; i++)
- {
- const char* transferSyntaxName =
- i == CtxBTFN ? "BTFN" : i == CtxNDR64 ? "NDR64" : "NDR32";
-
- if (bindResponse->Results[i].AckResult == RPC_BIND_NACK) // transfer syntax was declined
- {
- if (!IsNullGuid((BYTE*)&bindResponse->Results[i].TransferSyntax))
- {
- errorout(
- "\nWarning: Rejected transfer syntax %s did not return NULL Guid\n",
- transferSyntaxName
- );
- }
-
- if (bindResponse->Results[i].SyntaxVersion)
- {
- errorout(
- "\nWarning: Rejected transfer syntax %s did not return syntax version 0 but %u\n",
- transferSyntaxName,
- LE32(bindResponse->Results[i].SyntaxVersion)
- );
- }
-
- if (bindResponse->Results[i].AckReason == RPC_ABSTRACTSYNTAX_UNSUPPORTED)
- {
- errorout(
- "\nWarning: Transfer syntax %s does not support KMS activation\n",
- transferSyntaxName
- );
- }
- else if (bindResponse->Results[i].AckReason != RPC_SYNTAX_UNSUPPORTED)
- {
- errorout(
- "\nWarning: Rejected transfer syntax %s did not return ack reason RPC_SYNTAX_UNSUPPORTED\n",
- transferSyntaxName
- );
- }
-
- continue;
- }
-
- if (i == CtxBTFN) // BTFN
- {
- if (bindResponse->Results[i].AckResult != RPC_BIND_ACK)
- {
- errorout("\nWarning: BTFN did not respond with RPC_BIND_ACK or RPC_BIND_NACK\n");
- }
-
- if (bindResponse->Results[i].AckReason != LE16(3))
- {
- errorout("\nWarning: BTFN did not return expected feature mask 0x3 but 0x%X\n", (unsigned int)LE16(bindResponse->Results[i].AckReason));
- }
-
- if (verbose) printf("... BTFN ");
- RpcFlags.HasBTFN = TRUE;
-
- continue;
- }
-
- // NDR32 or NDR64 Ctx
- if (bindResponse->Results[i].AckResult != RPC_BIND_ACCEPT)
- {
- errorout(
- "\nFatal: transfer syntax %s returned an invalid status, neither RPC_BIND_ACCEPT nor RPC_BIND_NACK\n",
- transferSyntaxName
- );
-
- status = !0;
- }
-
- if (!IsEqualGUID(&bindResponse->Results[i].TransferSyntax, &bindRequest->CtxItems[i].TransferSyntax))
- {
- errorout(
- "\nFatal: Transfer syntax of RPC bind request and response does not match\n"
- );
-
- status = !0;
- }
-
- if (bindResponse->Results[i].SyntaxVersion != bindRequest->CtxItems[i].SyntaxVersion)
- {
- errorout("\nFatal: Expected transfer syntax version %u for %s but got %u\n",
- (uint32_t)LE32(bindRequest->CtxItems[0].SyntaxVersion),
- transferSyntaxName,
- (uint32_t)LE32(bindResponse->Results[0].SyntaxVersion)
- );
-
- status = !0;
- }
-
- // The ack reason field is actually undefined here but Microsoft sets this to 0
- if (bindResponse->Results[i].AckReason != 0)
- {
- errorout(
- "\nWarning: Ack reason should be 0 but is %u\n",
- LE16(bindResponse->Results[i].AckReason)
- );
- }
-
- if (!status)
- {
- if (i == CtxNDR64)
- {
- RpcFlags.HasNDR64 = TRUE;
- if (verbose) printf("... NDR64 ");
- }
- if (!i)
- {
- RpcFlags.HasNDR32 = TRUE;
- if (verbose) printf("... NDR32 ");
- }
-
- }
- }
- }
-
- free(bindResponseBytePtr);
-
- if (!RpcFlags.HasNDR64 && !RpcFlags.HasNDR32)
- {
- errorout("\nFatal: Could neither negotiate NDR32 nor NDR64 with the RPC server\n");
- status = !0;
- }
-
- return status;
-}
-
-RpcStatus rpcBindClient(const RpcCtx sock, const int_fast8_t verbose)
-{
- firstPacketSent = FALSE;
- RpcFlags.mask = 0;
-
- RpcStatus status =
- rpcBindOrAlterClientContext(sock, RPC_PT_BIND_REQ, verbose);
-
- if (status) return status;
-
- if (!RpcFlags.HasNDR32)
- status = rpcBindOrAlterClientContext(sock, RPC_PT_ALTERCONTEXT_REQ, verbose);
-
- return status;
-}
-
-#endif // USE_MSRPC
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#if !defined(_CRYPTO_OPENSSL) && !defined(_CRYPTO_POLARSSL) && !defined(_CRYPTO_WINDOWS)
-#include "crypto_internal.h"
-#include "endian.h"
-
-#define F0(x, y, z) ( ((x) & (y)) | (~(x) & (z)) )
-#define F1(x, y, z) ( ((x) & (y)) | ((x) & (z)) | ((y) & (z)) )
-
-#define SI1(x) ( ROR32(x, 2 ) ^ ROR32(x, 13) ^ ROR32(x, 22) )
-#define SI2(x) ( ROR32(x, 6 ) ^ ROR32(x, 11) ^ ROR32(x, 25) )
-#define SI3(x) ( ROR32(x, 7 ) ^ ROR32(x, 18) ^ ((x) >> 3 ) )
-#define SI4(x) ( ROR32(x, 17) ^ ROR32(x, 19) ^ ((x) >> 10) )
-
-static const DWORD k[] = {
- 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1,
- 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
- 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786,
- 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
- 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147,
- 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
- 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B,
- 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
- 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A,
- 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
- 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
-};
-
-
-static void Sha256Init(Sha256Ctx *Ctx)
-{
- Ctx->State[0] = 0x6A09E667;
- Ctx->State[1] = 0xBB67AE85;
- Ctx->State[2] = 0x3C6EF372;
- Ctx->State[3] = 0xA54FF53A;
- Ctx->State[4] = 0x510E527F;
- Ctx->State[5] = 0x9B05688C;
- Ctx->State[6] = 0x1F83D9AB;
- Ctx->State[7] = 0x5BE0CD19;
- Ctx->Len = 0;
-}
-
-
-static void Sha256ProcessBlock(Sha256Ctx *Ctx, BYTE *block)
-{
- unsigned int i;
- DWORD w[64], temp1, temp2;
- DWORD a = Ctx->State[0];
- DWORD b = Ctx->State[1];
- DWORD c = Ctx->State[2];
- DWORD d = Ctx->State[3];
- DWORD e = Ctx->State[4];
- DWORD f = Ctx->State[5];
- DWORD g = Ctx->State[6];
- DWORD h = Ctx->State[7];
-
- for (i = 0; i < 16; i++)
- //w[ i ] = GET_UAA32BE(block, i);
- w[i] = BE32(((DWORD*)block)[i]);
-
- for (i = 16; i < 64; i++)
- w[ i ] = SI4(w[ i - 2 ]) + w[ i - 7 ] + SI3(w[ i - 15 ]) + w[ i - 16 ];
-
- for (i = 0; i < 64; i++)
- {
- temp1 = h + SI2(e) + F0(e, f, g) + k[ i ] + w[ i ];
- temp2 = SI1(a) + F1(a, b, c);
-
- h = g;
- g = f;
- f = e;
- e = d + temp1;
- d = c;
- c = b;
- b = a;
- a = temp1 + temp2;
- }
-
- Ctx->State[0] += a;
- Ctx->State[1] += b;
- Ctx->State[2] += c;
- Ctx->State[3] += d;
- Ctx->State[4] += e;
- Ctx->State[5] += f;
- Ctx->State[6] += g;
- Ctx->State[7] += h;
-}
-
-
-static void Sha256Update(Sha256Ctx *Ctx, BYTE *data, size_t len)
-{
- unsigned int b_len = Ctx->Len & 63,
- r_len = (b_len ^ 63) + 1;
-
- Ctx->Len += len;
-
- if ( len < r_len )
- {
- memcpy(Ctx->Buffer + b_len, data, len);
- return;
- }
-
- if ( r_len < 64 )
- {
- memcpy(Ctx->Buffer + b_len, data, r_len);
- len -= r_len;
- data += r_len;
- Sha256ProcessBlock(Ctx, Ctx->Buffer);
- }
-
- for (; len >= 64; len -= 64, data += 64)
- Sha256ProcessBlock(Ctx, data);
-
- if ( len ) memcpy(Ctx->Buffer, data, len);
-}
-
-
-static void Sha256Finish(Sha256Ctx *Ctx, BYTE *hash)
-{
- unsigned int i, b_len = Ctx->Len & 63;
-
- Ctx->Buffer[ b_len ] = 0x80;
- if ( b_len ^ 63 ) memset(Ctx->Buffer + b_len + 1, 0, b_len ^ 63);
-
- if ( b_len >= 56 )
- {
- Sha256ProcessBlock(Ctx, Ctx->Buffer);
- memset(Ctx->Buffer, 0, 56);
- }
-
- //PUT_UAA64BE(Ctx->Buffer, (unsigned long long)(Ctx->Len * 8), 7);
- ((uint64_t*)Ctx->Buffer)[7] = BE64((uint64_t)Ctx->Len << 3);
- Sha256ProcessBlock(Ctx, Ctx->Buffer);
-
- for (i = 0; i < 8; i++)
- //PUT_UAA32BE(hash, Ctx->State[i], i);
- ((DWORD*)hash)[i] = BE32(Ctx->State[i]);
-
-}
-
-
-void Sha256(BYTE *data, size_t len, BYTE *hash)
-{
- Sha256Ctx Ctx;
-
- Sha256Init(&Ctx);
- Sha256Update(&Ctx, data, len);
- Sha256Finish(&Ctx, hash);
-}
-
-
-static void _Sha256HmacInit(Sha256HmacCtx *Ctx, BYTE *key, size_t klen)
-{
- BYTE IPad[64];
- unsigned int i;
-
- memset(IPad, 0x36, sizeof(IPad));
- memset(Ctx->OPad, 0x5C, sizeof(Ctx->OPad));
-
- if ( klen > 64 )
- {
- BYTE *temp = (BYTE*)alloca(32);
- Sha256(key, klen, temp);
- klen = 32;
- key = temp;
- }
-
- for (i = 0; i < klen; i++)
- {
- IPad[ i ] ^= key[ i ];
- Ctx->OPad[ i ] ^= key[ i ];
- }
-
- Sha256Init(&Ctx->ShaCtx);
- Sha256Update(&Ctx->ShaCtx, IPad, sizeof(IPad));
-}
-
-
-static void _Sha256HmacUpdate(Sha256HmacCtx *Ctx, BYTE *data, size_t len)
-{
- Sha256Update(&Ctx->ShaCtx, data, len);
-}
-
-
-static void _Sha256HmacFinish(Sha256HmacCtx *Ctx, BYTE *hmac)
-{
- BYTE temp[32];
-
- Sha256Finish(&Ctx->ShaCtx, temp);
- Sha256Init(&Ctx->ShaCtx);
- Sha256Update(&Ctx->ShaCtx, Ctx->OPad, sizeof(Ctx->OPad));
- Sha256Update(&Ctx->ShaCtx, temp, sizeof(temp));
- Sha256Finish(&Ctx->ShaCtx, hmac);
-}
-
-
-
-int_fast8_t Sha256Hmac(BYTE* key, BYTE* restrict data, DWORD len, BYTE* restrict hmac)
-{
- Sha256HmacCtx Ctx;
- _Sha256HmacInit(&Ctx, key, 16);
- _Sha256HmacUpdate(&Ctx, data, len);
- _Sha256HmacFinish(&Ctx, hmac);
- return TRUE;
-}
-
-
-#endif // No external Crypto
-
-/*
- * dns_srv.c
- *
- * This file contains the code for KMS SRV record lookup in DNS (_vlmcs._tcp.example.com IN SRV 0 0 1688 mykms.example.com)
- *
- */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef NO_DNS
-
-#include "dns_srv.h"
-
-#include
-#include
-#ifndef _WIN32
-#include
-#include
-#include
-#include
-#include
-//#ifndef DNS_PARSER_INTERNAL
-#if __ANDROID__
-#include
-#include "nameser.h"
-#include "resolv.h"
-#else // other Unix non-Android
-#include
-#include
-#include
-#endif // other Unix non-Android
-//#endif // DNS_PARSER_INTERNAL
-#else // WIN32
-#include
-#endif // WIN32
-
-#include "helpers.h"
-#include "output.h"
-#include "endian.h"
-
-#if defined(DNS_PARSER_INTERNAL) && !defined(_WIN32)
-
-#include "ns_name.h"
-#include "ns_parse.h"
-
-// Define macros to redirect DNS parser functions to internal versions
-
-#undef ns_msg
-#undef ns_initparse
-#undef ns_parserr
-#undef ns_rr
-#undef ns_name_uncompress
-#undef ns_msg_base
-#undef ns_msg_end
-#undef ns_rr_rdata
-#undef ns_rr_type
-#undef ns_msg_count
-#undef ns_rr_class
-#undef ns_s_an
-#define ns_msg ns_msg_vlmcsd
-#define ns_initparse ns_initparse_vlmcsd
-#define ns_parserr ns_parserr_vlmcsd
-#define ns_rr ns_rr_vlmcsd
-#define ns_name_uncompress ns_name_uncompress_vlmcsd
-#define ns_msg_base ns_msg_base_vlmcsd
-#define ns_msg_end ns_msg_end_vlmcsd
-#define ns_rr_rdata ns_rr_rdata_vlmcsd
-#define ns_rr_type ns_rr_type_vlmcsd
-#define ns_msg_count ns_msg_count_vlmcsd
-#define ns_rr_class ns_rr_class_vlmcsd
-#define ns_s_an ns_s_an_vlmcsd
-
-#ifndef NS_MAXLABEL
-#define NS_MAXLABEL 63
-#endif
-
-#endif // defined(DNS_PARSER_INTERNAL) && !defined(_WIN32)
-
-
-//TODO: maybe move to helpers.c
-static unsigned int isqrt(unsigned int n)
-{
- unsigned int c = 0x8000;
- unsigned int g = 0x8000;
-
- for(;;)
- {
- if(g*g > n)
- g ^= c;
-
- c >>= 1;
-
- if(c == 0) return g;
-
- g |= c;
- }
-}
-
-
-/*
- * Compare function for qsort to sort SRV records by priority and weight
- * random_weight must be product of weight from SRV record and square root of a random number
- */
-static int kmsServerListCompareFunc1(const void* a, const void* b)
-{
- if ( !a && !b) return 0;
- if ( a && !b) return -1;
- if ( !a && b) return 1;
-
- int priority_order = (int)((*(kms_server_dns_ptr*)a)->priority) - ((int)(*(kms_server_dns_ptr*)b)->priority);
-
- if (priority_order) return priority_order;
-
- return (int)((*(kms_server_dns_ptr*)b)->random_weight) - ((int)(*(kms_server_dns_ptr*)a)->random_weight);
-}
-
-/* Sort resulting SRV records */
-void sortSrvRecords(kms_server_dns_ptr* serverlist, const int answers)
-{
- int i;
-
- for (i = 0; i < answers; i++)
- {
- serverlist[i]->random_weight = (rand32() % 256) * isqrt(serverlist[i]->weight * 1000);
- }
-
- qsort(serverlist, answers, sizeof(kms_server_dns_ptr), kmsServerListCompareFunc1);
-}
-
-
-#define RECEIVE_BUFFER_SIZE 2048
-#ifndef _WIN32 // UNIX resolver
-
-/*
- * Retrieves a raw DNS answer (a buffer of what came over the net)
- * Result must be parsed
- */
-static int getDnsRawAnswer(const char *restrict query, unsigned char** receive_buffer)
-{
- if (res_init() < 0)
- {
- errorout("Cannot initialize resolver: %s", strerror(errno));
- return 0;
- }
-
- //if(!(*receive_buffer = (unsigned char*)malloc(RECEIVE_BUFFER_SIZE))) OutOfMemory();
- *receive_buffer = (unsigned char*)vlmcsd_malloc(RECEIVE_BUFFER_SIZE);
-
- int bytes_received;
-
- if (*query == '.')
- {
-# if __ANDROID__ || __GLIBC__ /* including __UCLIBC__*/ || __APPLE__ || __CYGWIN__ || __FreeBSD__ || __NetBSD__ || __DragonFly__ || __OpenBSD__ || __sun__
- bytes_received = res_querydomain("_vlmcs._tcp", query + 1, ns_c_in, ns_t_srv, *receive_buffer, RECEIVE_BUFFER_SIZE);
-# else
- char* querystring = (char*)alloca(strlen(query) + 12);
- strcpy(querystring, "_vlmcs._tcp");
- strcat(querystring, query);
- bytes_received = res_query(querystring, ns_c_in, ns_t_srv, *receive_buffer, RECEIVE_BUFFER_SIZE);
-# endif
- }
- else
- {
- bytes_received = res_search("_vlmcs._tcp", ns_c_in, ns_t_srv, *receive_buffer, RECEIVE_BUFFER_SIZE);
- }
-
- if (bytes_received < 0)
- {
- errorout("Fatal: DNS query to %s%s failed: %s\n", "_vlmcs._tcp", *query == '.' ? query : "", hstrerror(h_errno));
- return 0;
- }
-
- return bytes_received;
-}
-
-/*
- * Retrieves an unsorted array of SRV records (Unix / Posix)
- */
-int getKmsServerList(kms_server_dns_ptr** serverlist, const char *restrict query)
-{
- unsigned char* receive_buffer;
- *serverlist = NULL;
-
- int bytes_received = getDnsRawAnswer(query, &receive_buffer);
-
- if (bytes_received == 0) return 0;
-
- ns_msg msg;
-
- if (ns_initparse(receive_buffer, bytes_received, &msg) < 0)
- {
- errorout("Fatal: Incorrect DNS response: %s\n", strerror(errno));
- free(receive_buffer);
- return 0;
- }
-
- uint16_t i, answers = ns_msg_count(msg, ns_s_an);
- //if(!(*serverlist = (kms_server_dns_ptr*)malloc(answers * sizeof(kms_server_dns_ptr)))) OutOfMemory();
- *serverlist = (kms_server_dns_ptr*)malloc(answers * sizeof(kms_server_dns_ptr));
-
- memset(*serverlist, 0, answers * sizeof(kms_server_dns_ptr));
-
- for (i = 0; i < answers; i++)
- {
- ns_rr rr;
-
- if (ns_parserr(&msg, ns_s_an, i, &rr) < 0)
- {
- errorout("Warning: Error in DNS resource record: %s\n", strerror(errno));
- continue;
- }
-
- if (ns_rr_type(rr) != ns_t_srv)
- {
- errorout("Warning: DNS server returned non-SRV record\n");
- continue;
- }
-
- if (ns_rr_class(rr) != ns_c_in)
- {
- errorout("Warning: DNS server returned non-IN class record\n");
- continue;
- }
-
- dns_srv_record_ptr srvrecord = (dns_srv_record_ptr)ns_rr_rdata(rr);
- kms_server_dns_ptr kms_server = (kms_server_dns_ptr)vlmcsd_malloc(sizeof(kms_server_dns_t));
-
- (*serverlist)[i] = kms_server;
-
- if (ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), srvrecord->name, kms_server->serverName, sizeof(kms_server->serverName)) < 0)
- {
- errorout("Warning: No valid DNS name returned in SRV record: %s\n", strerror(errno));
- continue;
- }
-
- sprintf(kms_server->serverName + strlen(kms_server->serverName), ":%hu", GET_UA16BE(&srvrecord->port));
- kms_server->priority = GET_UA16BE(&srvrecord->priority);
- kms_server->weight = GET_UA16BE(&srvrecord->weight);
-
- }
-
- free(receive_buffer);
- return answers;
-}
-
-#else // WIN32 (Windows Resolver)
-
-/*
- * Retrieves an unsorted array of SRV records (Windows)
- */
-int getKmsServerList(kms_server_dns_ptr** serverlist, const char *const restrict query)
-{
-# define MAX_DNS_NAME_SIZE 254
- *serverlist = NULL;
- PDNS_RECORD receive_buffer;
- char dnsDomain[MAX_DNS_NAME_SIZE];
- char FqdnQuery[MAX_DNS_NAME_SIZE];
- DWORD size = MAX_DNS_NAME_SIZE;
- DNS_STATUS result;
- int answers = 0;
- PDNS_RECORD dns_iterator;
-
- if (*query == '-')
- {
- if (!GetComputerNameExA(ComputerNamePhysicalDnsDomain, dnsDomain, &size))
- {
- errorout("Fatal: Could not determine computer's DNS name: %s\n", vlmcsd_strerror(GetLastError()));
- return 0;
- }
-
- strcpy(FqdnQuery, "_vlmcs._tcp.");
- strncat(FqdnQuery, dnsDomain, MAX_DNS_NAME_SIZE - 12);
- }
- else
- {
- strcpy(FqdnQuery, "_vlmcs._tcp");
- strncat(FqdnQuery, query, MAX_DNS_NAME_SIZE - 11);
- }
-
- if ((result = DnsQuery_UTF8(FqdnQuery, DNS_TYPE_SRV, 0, NULL, &receive_buffer, NULL)) != 0)
- {
- errorout("Fatal: DNS query to %s failed: %s\n", FqdnQuery, vlmcsd_strerror(result));
- return 0;
- }
-
- for (dns_iterator = receive_buffer; dns_iterator; dns_iterator = dns_iterator->pNext)
- {
- if (dns_iterator->Flags.S.Section != 1) continue;
-
- if (dns_iterator->wType != DNS_TYPE_SRV)
- {
- errorout("Warning: DNS server returned non-SRV record\n");
- continue;
- }
-
- answers++;
- }
-
- *serverlist = (kms_server_dns_ptr*)vlmcsd_malloc(answers * sizeof(kms_server_dns_ptr));
-
- for (answers = 0, dns_iterator = receive_buffer; dns_iterator; dns_iterator = dns_iterator->pNext)
- {
- if (dns_iterator->wType != DNS_TYPE_SRV) continue;
-
- kms_server_dns_ptr kms_server = (kms_server_dns_ptr)vlmcsd_malloc(sizeof(kms_server_dns_t));
-
- memset(kms_server, 0, sizeof(kms_server_dns_t));
-
- snprintf(kms_server->serverName, sizeof(kms_server->serverName), "%s:%hu", dns_iterator->Data.SRV.pNameTarget, dns_iterator->Data.SRV.wPort);
- kms_server->priority = dns_iterator->Data.SRV.wPriority;
- kms_server->weight = dns_iterator->Data.SRV.wWeight;
-
- (*serverlist)[answers++] = kms_server;
- }
-
- //sortSrvRecords(*serverlist, answers, NoSrvRecordPriority);
-
- DnsRecordListFree(receive_buffer, DnsFreeRecordList);
-
- return answers;
-# undef MAX_DNS_NAME_SIZE
-}
-#endif // _WIN32
-#undef RECEIVE_BUFFER_SIZE
-#endif // NO_DNS
-
-
-/*
- * Copyright (c) 1996,1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Modified by Hotbird64 for use with vlmcs.
- */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifdef DNS_PARSER_INTERNAL
-#ifndef NO_DNS
-
-/* Import. */
-
-#include
-#include
-#include
-
-#include "types.h"
-#include "endian.h"
-#include "ns_name.h"
-#include "ns_parse.h"
-
-/* Macros. */
-
-#define NS_GET16_VLMCSD(s, cp) do { \
- (s) = GET_UA16BE(cp); \
- (cp) += NS_INT16SZ; \
-} while (0)
-
-#define NS_GET32_VLMCSD(l, cp) do { \
- (l) = GET_UA32BE(cp); \
- (cp) += NS_INT32SZ; \
-} while (0)
-
-#define RETERR(err) do { errno = (err); return (-1); } while (0)
-
-/* Forward. */
-
-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)
-{
- const unsigned char *p;
- for (p=s; p=192)
- {if (p+1 0; count--) {
- int b, rdlength;
-
- b = dn_skipname_vlmcsd(ptr, eom);
- if (b < 0)
- RETERR(EMSGSIZE);
- ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
- if (section != ns_s_qd_vlmcsd) {
- if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
- RETERR(EMSGSIZE);
- ptr += NS_INT32SZ/*TTL*/;
- NS_GET16_VLMCSD(rdlength, ptr);
- ptr += rdlength/*RData*/;
- }
- }
- if (ptr > eom)
- RETERR(EMSGSIZE);
- return (ptr - optr);
-}
-
-int
-ns_initparse_vlmcsd(const uint8_t *msg, int msglen, ns_msg_vlmcsd *handle) {
- const uint8_t *eom = msg + msglen;
- int i;
-
- memset(handle, 0x5e, sizeof *handle);
- handle->_msg = msg;
- handle->_eom = eom;
- if (msg + NS_INT16SZ > eom)
- RETERR(EMSGSIZE);
- NS_GET16_VLMCSD(handle->_id, msg);
- if (msg + NS_INT16SZ > eom)
- RETERR(EMSGSIZE);
- NS_GET16_VLMCSD(handle->_flags, msg);
- for (i = 0; i < ns_s_max_vlmcsd; i++) {
- if (msg + NS_INT16SZ > eom)
- RETERR(EMSGSIZE);
- NS_GET16_VLMCSD(handle->_counts[i], msg);
- }
- for (i = 0; i < ns_s_max_vlmcsd; i++)
- if (handle->_counts[i] == 0)
- handle->_sections[i] = NULL;
- else {
- int b = ns_skiprr_vlmcsd(msg, eom, (ns_sect_vlmcsd)i,
- handle->_counts[i]);
-
- if (b < 0)
- return (-1);
- handle->_sections[i] = msg;
- msg += b;
- }
- if (msg > eom)
- RETERR(EMSGSIZE);
- handle->_eom = msg;
- setsection_vlmcsd(handle, ns_s_max_vlmcsd);
- return (0);
-}
-
-int
-ns_parserr_vlmcsd(ns_msg_vlmcsd *handle, ns_sect_vlmcsd section, int rrnum, ns_rr_vlmcsd *rr) {
- int b;
-
- /* Make section right. */
- if (section >= ns_s_max_vlmcsd)
- RETERR(ENODEV);
- if (section != handle->_sect)
- setsection_vlmcsd(handle, section);
-
- /* Make rrnum right. */
- if (rrnum == -1)
- rrnum = handle->_rrnum;
- if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
- RETERR(ENODEV);
- if (rrnum < handle->_rrnum)
- setsection_vlmcsd(handle, section);
- if (rrnum > handle->_rrnum) {
- b = ns_skiprr_vlmcsd(handle->_msg_ptr, handle->_eom, section,
- rrnum - handle->_rrnum);
-
- if (b < 0)
- return (-1);
- handle->_msg_ptr += b;
- handle->_rrnum = rrnum;
- }
-
- /* Do the parse. */
- b = ns_name_uncompress_vlmcsd(handle->_msg, handle->_eom,
- handle->_msg_ptr, rr->name, NS_MAXDNAME);
- if (b < 0)
- return (-1);
- handle->_msg_ptr += b;
- if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
- RETERR(EMSGSIZE);
- NS_GET16_VLMCSD(rr->type, handle->_msg_ptr);
- NS_GET16_VLMCSD(rr->rr_class, handle->_msg_ptr);
- if (section == ns_s_qd_vlmcsd) {
- rr->ttl = 0;
- rr->rdlength = 0;
- rr->rdata = NULL;
- } else {
- if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
- RETERR(EMSGSIZE);
- NS_GET32_VLMCSD(rr->ttl, handle->_msg_ptr);
- NS_GET16_VLMCSD(rr->rdlength, handle->_msg_ptr);
- if (handle->_msg_ptr + rr->rdlength > handle->_eom)
- RETERR(EMSGSIZE);
- rr->rdata = handle->_msg_ptr;
- handle->_msg_ptr += rr->rdlength;
- }
- if (++handle->_rrnum > handle->_counts[(int)section])
- setsection_vlmcsd(handle, (ns_sect_vlmcsd)((int)section + 1));
-
- /* All done. */
- return (0);
-}
-
-/* Private. */
-
-static void
-setsection_vlmcsd(ns_msg_vlmcsd *msg, ns_sect_vlmcsd sect) {
- msg->_sect = sect;
- if (sect == ns_s_max_vlmcsd) {
- msg->_rrnum = -1;
- msg->_msg_ptr = NULL;
- } else {
- msg->_rrnum = 0;
- msg->_msg_ptr = msg->_sections[(int)sect];
- }
-}
-
-#endif // !NO_DNS
-#endif // DNS_PARSER_INTERNAL
-/*
- * Copyright (c) 1996,1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Modified by Hotbird64 for use with vlmcs.
- */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifdef DNS_PARSER_INTERNAL
-#ifndef NO_DNS
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "types.h"
-#include "ns_name.h"
-
-#ifdef SPRINTF_CHAR
-# define SPRINTF(x) strlen(sprintf/**/x)
-#else
-# define SPRINTF(x) ((size_t)sprintf x)
-#endif
-
-#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */
-#define DNS_LABELTYPE_BITSTRING 0x41
-
-#define NS_MAXCDNAME 255
-#define NS_CMPRSFLGS 0xc0
-
-/* Data. */
-
-static char digits[] = "0123456789";
-
-
-/* Forward. */
-
-static int special_vlmcsd(int);
-static int printable_vlmcsd(int);
-static int labellen_vlmcsd(const uint8_t *);
-static int decode_bitstring_vlmcsd(const char **, char *, const char *);
-
-/*
- * ns_name_ntop(src, dst, dstsiz)
- * Convert an encoded domain name to printable ascii as per RFC1035.
- * return:
- * Number of bytes written to buffer, or -1 (with errno set)
- * notes:
- * The root is returned as "."
- * All other domains are returned in non absolute form
- */
-static int
-ns_name_ntop_vlmcsd(const uint8_t *src, char *dst, size_t dstsiz)
-{
- const uint8_t *cp;
- char *dn, *eom;
- uint8_t c;
- uint32_t n;
- int l;
-
- cp = src;
- dn = dst;
- eom = dst + dstsiz;
-
- while ((n = *cp++) != 0) {
- if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
- /* Some kind of compression pointer. */
- errno = EMSGSIZE;
- return (-1);
- }
- if (dn != dst) {
- if (dn >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '.';
- }
- if ((l = labellen_vlmcsd(cp - 1)) < 0) {
- errno = EMSGSIZE; /* XXX */
- return(-1);
- }
- if (dn + l >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
- int m;
-
- if (n != DNS_LABELTYPE_BITSTRING) {
- /* XXX: labellen should reject this case */
- errno = EINVAL;
- return(-1);
- }
- if ((m = decode_bitstring_vlmcsd((const char **)&cp, dn, eom)) < 0)
- {
- errno = EMSGSIZE;
- return(-1);
- }
- dn += m;
- continue;
- }
- for ((void)NULL; l > 0; l--) {
- c = *cp++;
- if (special_vlmcsd(c)) {
- if (dn + 1 >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '\\';
- *dn++ = (char)c;
- } else if (!printable_vlmcsd(c)) {
- if (dn + 3 >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '\\';
- *dn++ = digits[c / 100];
- *dn++ = digits[(c % 100) / 10];
- *dn++ = digits[c % 10];
- } else {
- if (dn >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = (char)c;
- }
- }
- }
- if (dn == dst) {
- if (dn >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '.';
- }
- if (dn >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '\0';
- return (dn - dst);
-}
-
-static int
-ns_name_unpack_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src,
- uint8_t *dst, size_t dstsiz)
-{
- const uint8_t *srcp, *dstlim;
- uint8_t *dstp;
- int n, len, checked, l;
-
- len = -1;
- checked = 0;
- dstp = dst;
- srcp = src;
- dstlim = dst + dstsiz;
- if (srcp < msg || srcp >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- /* Fetch next label in domain name. */
- while ((n = *srcp++) != 0) {
- /* Check for indirection. */
- switch (n & NS_CMPRSFLGS) {
- case 0:
- case NS_TYPE_ELT:
- /* Limit checks. */
- if ((l = labellen_vlmcsd(srcp - 1)) < 0) {
- errno = EMSGSIZE;
- return(-1);
- }
- if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- checked += l + 1;
- *dstp++ = n;
- memcpy(dstp, srcp, l);
- dstp += l;
- srcp += l;
- break;
-
- case NS_CMPRSFLGS:
- if (srcp >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- if (len < 0)
- len = srcp - src + 1;
- srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
- if (srcp < msg || srcp >= eom) { /* Out of range. */
- errno = EMSGSIZE;
- return (-1);
- }
- checked += 2;
- /*
- * Check for loops in the compressed name;
- * if we've looked at the whole message,
- * there must be a loop.
- */
- if (checked >= eom - msg) {
- errno = EMSGSIZE;
- return (-1);
- }
- break;
-
- default:
- errno = EMSGSIZE;
- return (-1); /* flag error */
- }
- }
- *dstp = '\0';
- if (len < 0)
- len = srcp - src;
- return (len);
-}
-
-
-/*
- * ns_name_uncompress_vlmcsd(msg, eom, src, dst, dstsiz)
- * Expand compressed domain name to presentation format.
- * return:
- * Number of bytes read out of `src', or -1 (with errno set).
- * note:
- * Root domain returns as "." not "".
- */
-int
-ns_name_uncompress_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src,
- char *dst, size_t dstsiz)
-{
- uint8_t tmp[NS_MAXCDNAME];
- int n;
-
- if ((n = ns_name_unpack_vlmcsd(msg, eom, src, tmp, sizeof tmp)) == -1)
- return (-1);
- if (ns_name_ntop_vlmcsd(tmp, dst, dstsiz) == -1)
- return (-1);
- return (n);
-}
-
-/*
- * special(ch)
- * Thinking in noninternationalized USASCII (per the DNS spec),
- * is this characted special ("in need of quoting") ?
- * return:
- * boolean.
- */
-static int
-special_vlmcsd(int ch) {
- switch (ch) {
- case 0x22: /* '"' */
- case 0x2E: /* '.' */
- case 0x3B: /* ';' */
- case 0x5C: /* '\\' */
- case 0x28: /* '(' */
- case 0x29: /* ')' */
- /* Special modifiers in zone files. */
- case 0x40: /* '@' */
- case 0x24: /* '$' */
- return (1);
- default:
- return (0);
- }
-}
-
-/*
- * printable(ch)
- * Thinking in noninternationalized USASCII (per the DNS spec),
- * is this character visible and not a space when printed ?
- * return:
- * boolean.
- */
-static int
-printable_vlmcsd(int ch) {
- return (ch > 0x20 && ch < 0x7f);
-}
-
-static int
-decode_bitstring_vlmcsd(const char **cpp, char *dn, const char *eom)
-{
- const char *cp = *cpp;
- char *beg = dn, tc;
- int b, blen, plen;
-
- if ((blen = (*cp & 0xff)) == 0)
- blen = 256;
- plen = (blen + 3) / 4;
- plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
- if (dn + plen >= eom)
- return(-1);
-
- cp++;
- dn += SPRINTF((dn, "\\[x"));
- for (b = blen; b > 7; b -= 8, cp++)
- dn += SPRINTF((dn, "%02x", *cp & 0xff));
- if (b > 4) {
- tc = *cp++;
- dn += SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
- } else if (b > 0) {
- tc = *cp++;
- dn += SPRINTF((dn, "%1x",
- ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
- }
- dn += SPRINTF((dn, "/%d]", blen));
-
- *cpp = cp;
- return(dn - beg);
-}
-
-static int
-labellen_vlmcsd(const uint8_t *lp)
-{
- int bitlen;
- uint8_t l = *lp;
-
- if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
- /* should be avoided by the caller */
- return(-1);
- }
-
- if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
- if (l == DNS_LABELTYPE_BITSTRING) {
- if ((bitlen = *(lp + 1)) == 0)
- bitlen = 256;
- return((bitlen + 7 ) / 8 + 1);
- }
- return(-1); /* unknwon ELT */
- }
- return(l);
-}
-
-#endif // !NO_DNS
-#endif // DNS_PARSER_INTERNAL
diff --git a/vlmcsd.7 b/vlmcsd.7
index f92ae6a..3df3b39 100644
--- a/vlmcsd.7
+++ b/vlmcsd.7
@@ -1,4 +1,4 @@
-.TH VLMCSD 7 "June 2014" "Hotbird64" "KMS Activation Manual"
+.TH VLMCSD 7 "March 2016" "Hotbird64" "KMS Activation Manual"
.SH NAME
vlmcsd\ \-\ a guide to KMS activation using vlmcsd
@@ -41,6 +41,14 @@ Office 2013: http://technet.microsoft.com/en-us/library/dn385360.aspx
.PP
These lists only include products that Microsoft sells to corporations via volume license contracts. For Windows there are inofficial GVLKs that work with consumer-only versions of Windows. Here is a list:
.PP
+TX9XD\-98N7V\-6WMQ6\-BX7FG\-H8Q99 - Windows 10 Home
+.br
+3KHY7\-WNT83\-DGQKR\-F7HPR\-844BM - Windows 10 Home N
+.br
+7HNRX\-D7KGG\-3K4RQ\-4WPJ4\-YTDFH - Windows 10 Home Single Language
+.br
+PVMJN\-6DFY6\-9CCP6\-7BKTT\-D3WVR - Windows 10 Home Country Specific
+.br
789NJ\-TQK6T\-6XTH8\-J39CJ\-J8D3P - Windows 8.1 Professional with Media Center
.br
M9Q9P\-WNJJT\-6PXPY\-DWX8H\-6XWKK - Windows 8.1 Core
diff --git a/vlmcsd.7.dos.txt b/vlmcsd.7.dos.txt
index fb2efab..5989bfb 100644
--- a/vlmcsd.7.dos.txt
+++ b/vlmcsd.7.dos.txt
@@ -76,6 +76,10 @@ DESCRIPTION
via volume license contracts. For Windows there are inofficial GVLKs
that work with consumer-only versions of Windows. Here is a list:
+ TX9XD-98N7V-6WMQ6-BX7FG-H8Q99 - Windows 10 Home
+ 3KHY7-WNT83-DGQKR-F7HPR-844BM - Windows 10 Home N
+ 7HNRX-D7KGG-3K4RQ-4WPJ4-YTDFH - Windows 10 Home Single Language
+ PVMJN-6DFY6-9CCP6-7BKTT-D3WVR - Windows 10 Home Country Specific
789NJ-TQK6T-6XTH8-J39CJ-J8D3P - Windows 8.1 Professional with Media
Center
M9Q9P-WNJJT-6PXPY-DWX8H-6XWKK - Windows 8.1 Core
@@ -219,4 +223,4 @@ SEE ALSO
-Hotbird64 June 2014 VLMCSD(7)
+Hotbird64 March 2016 VLMCSD(7)
diff --git a/vlmcsd.7.html b/vlmcsd.7.html
index 6af88a0..d9944c8 100644
--- a/vlmcsd.7.html
+++ b/vlmcsd.7.html
@@ -1,5 +1,5 @@
-
+
@@ -169,8 +169,16 @@ inofficial GVLKs that work with consumer-only versions of
Windows. Here is a list:
- 789NJ−TQK6T−6XTH8−J39CJ−J8D3P
-- Windows 8.1 Professional with Media Center
+ TX9XD−98N7V−6WMQ6−BX7FG−H8Q99
+- Windows 10 Home
+3KHY7−WNT83−DGQKR−F7HPR−844BM -
+Windows 10 Home N
+7HNRX−D7KGG−3K4RQ−4WPJ4−YTDFH -
+Windows 10 Home Single Language
+PVMJN−6DFY6−9CCP6−7BKTT−D3WVR -
+Windows 10 Home Country Specific
+789NJ−TQK6T−6XTH8−J39CJ−J8D3P -
+Windows 8.1 Professional with Media Center
M9Q9P−WNJJT−6PXPY−DWX8H−6XWKK -
Windows 8.1 Core
7B9N3−D94CG−YTVHR−QBPX3−RJP64 -
diff --git a/vlmcsd.7.pdf b/vlmcsd.7.pdf
index dc2d776..80ae4f8 100644
Binary files a/vlmcsd.7.pdf and b/vlmcsd.7.pdf differ
diff --git a/vlmcsd.7.unix.txt b/vlmcsd.7.unix.txt
index 4b28ad8..a84b424 100644
--- a/vlmcsd.7.unix.txt
+++ b/vlmcsd.7.unix.txt
@@ -76,6 +76,10 @@ DESCRIPTION
via volume license contracts. For Windows there are inofficial GVLKs
that work with consumer-only versions of Windows. Here is a list:
+ TX9XD-98N7V-6WMQ6-BX7FG-H8Q99 - Windows 10 Home
+ 3KHY7-WNT83-DGQKR-F7HPR-844BM - Windows 10 Home N
+ 7HNRX-D7KGG-3K4RQ-4WPJ4-YTDFH - Windows 10 Home Single Language
+ PVMJN-6DFY6-9CCP6-7BKTT-D3WVR - Windows 10 Home Country Specific
789NJ-TQK6T-6XTH8-J39CJ-J8D3P - Windows 8.1 Professional with Media
Center
M9Q9P-WNJJT-6PXPY-DWX8H-6XWKK - Windows 8.1 Core
@@ -219,4 +223,4 @@ SEE ALSO
-Hotbird64 June 2014 VLMCSD(7)
+Hotbird64 March 2016 VLMCSD(7)
diff --git a/vlmcsd.8 b/vlmcsd.8
index 26b44e3..e8ad3c1 100644
--- a/vlmcsd.8
+++ b/vlmcsd.8
@@ -1,5 +1,5 @@
.mso www.tmac
-.TH VLMCSD 8 "September 2015" "Hotbird64" "KMS Activation Manual"
+.TH VLMCSD 8 "June 2016" "Hotbird64" "KMS Activation Manual"
.LO 8
.SH NAME
@@ -27,6 +27,9 @@ All options that do no require an argument may be combined with a single dash, f
.IP "\fB-h\fR or \fB-?\fR"
Displays help.
+.IP "\fB-V\fR"
+Displays extended version information. This includes the compiler used to build vlmcsd, the intended platform and flags (compile time options) to build vlmcsd. If you have the source code of vlmcsd, you can type \fBmake help\fR (or \fBgmake help\fR on systems that do not use the GNU version of \fBmake\fR(1) by default) to see the meaning of those flags.
+
.IP "\fB-L\fR \fIipaddress\fR[:\fIport\fR]"
Instructs vlmcsd to listen on \fIipaddress\fR with optional \fIport\fR (default 1688). You can use this option more than once. If you do not specify \fB-L\fR at least once, IP addresses 0.0.0.0 (IPv4) and :: (IPv6) are used. If the IP address contains colons (IPv6) you must enclose the IP address in brackets if you specify the optional port, e.g. [2001:db8::dead:beef]:1688.
.PP
@@ -39,11 +42,8 @@ If you specify a link local IPv6 address (fe80::/10, usually starting with fe80:
.IP "\fB-P\fR \fIport"
Use TCP \fIport\fR for all subsequent \fB-L\fR statements that do not include an optional port. If you use \fB-P\fR and \fB-L\fR, \fB-P\fR must be specified before \fB-L\fR.
-.IP "\fB-4\fR and \fB-6\fR"
-Used to control the use of IPv4 and IPv4 if you did not use -L. If you specify both \fB-4\fR and \fB-6\fR or none, vlmcsd uses both protocols. If you specify only one, that protocol will be used only. \fBThese options are deprecated and will be removed.\fR
-
-.IP "\fB-I\fR"
-This option is deprecated and does nothing. It is provided for compatibility with svn681 and earlier versions only. It will be removed in a future release.
+.IP "\fB-F0\fR and \fB-F1\fR
+Allow (\fB-F1\fR) or disallow (\fB-F0\fR) binding to IP addresses that are currently not configured on your system. The default is \fB-F0\fR. \fB-F1\fR allows you to bind to an IP address that may be configured after you started \fBvlmcsd\fR. \fBvlmcsd\fR will listen on that address as soon as it becomes available. This feature is only available under Linux (IPv4 and IPv6) and FreeBSD (IPv4 only). FreeBSD allows this feature only for the root user (more correctly: processes that have the PRIV_NETINET_BINDANY privilege). Linux does not require a capability for this.
.IP "\fB-t\fR \fIseconds\fR"
Timeout the TCP connection with the client after \fIseconds\fR seconds. After sending an activation request. RPC keeps the TCP connection for a while. The default is 30 seconds. You may specify a shorter period to free ressources on your device faster. This is useful for devices with limited main memory or if you used \fB-m\fR to limit the concurrent clients that may request activation. Microsoft RPC clients disconnect after 30 seconds by default. Setting \fIseconds\fR to a greater value does not make much sense.
@@ -79,9 +79,6 @@ The native Windows version never daemonizes and always behaves as if \fB-D\fR ha
.IP "\fB-e\fR"
If specified, vlmcsd ignores \fB-l\fR and writes all logging output to \fBstdout\fR(3). This is mainly useful for testing and debugging and often combined with \fB-D\fR.
-.IP "\fB-f\fR"
-This flag combines \fB-D\fR and \fB-e\fR. So typing "vlmcsd -f" is identical to "vlmcsd -De". The purpose of \fB-f\fR is to provide compatibility with previous versions of vlmcsd. \fBThis option is deprecated and will be removed.\fR
-
.IP "\fB-v\fR"
Use verbose logging. Logs every parameter of the base request and the base response. It also logs the HWID of the KMS server if KMS protocol version 6 is used. This option is mainly for debugging purposes. It only has an effect if some form of logging is used. Thus \fB-v\fR does not make sense if not used with \fB-l\fR, \fB-e\fR or \fB-f\fR.
diff --git a/vlmcsd.8.dos.txt b/vlmcsd.8.dos.txt
index 674f03b..20bbb3f 100644
--- a/vlmcsd.8.dos.txt
+++ b/vlmcsd.8.dos.txt
@@ -52,46 +52,54 @@ OPTIONS
Displays help.
+ -V Displays extended version information. This includes the com‐
+ piler used to build vlmcsd, the intended platform and flags
+ (compile time options) to build vlmcsd. If you have the source
+ code of vlmcsd, you can type make help (or gmake help on systems
+ that do not use the GNU version of make(1) by default) to see
+ the meaning of those flags.
+
+
-L ipaddress[:port]
- Instructs vlmcsd to listen on ipaddress with optional port
- (default 1688). You can use this option more than once. If you
+ Instructs vlmcsd to listen on ipaddress with optional port
+ (default 1688). You can use this option more than once. If you
do not specify -L at least once, IP addresses 0.0.0.0 (IPv4) and
:: (IPv6) are used. If the IP address contains colons (IPv6) you
- must enclose the IP address in brackets if you specify the
+ must enclose the IP address in brackets if you specify the
optional port, e.g. [2001:db8::dead:beef]:1688.
- If no port is specified, vlmcsd uses the default port according
- to a preceding -P option. If you specify a port, it can be a
- number (1-65535) or a name (usually found in /etc/services if
+ If no port is specified, vlmcsd uses the default port according
+ to a preceding -P option. If you specify a port, it can be a
+ number (1-65535) or a name (usually found in /etc/services if
not provided via LDAP, NIS+ or another name service).
- If you specify a link local IPv6 address (fe80::/10, usually
+ If you specify a link local IPv6 address (fe80::/10, usually
starting with fe80::), it must be followed by a percent sign (%)
- and a scope id (=network interface name or number) on most
- unixoid OSses including Linux, Android, MacOS X and iOS, e.g.
+ and a scope id (=network interface name or number) on most
+ unixoid OSses including Linux, Android, MacOS X and iOS, e.g.
fe80::1234:56ff:fe78:9abc%eth0 or
- [fe80::1234:56ff:fe78:9abc%2]:1688. Windows (including cygwin)
- does not require a scope id unless the same link local address
- is used on more than one network interface. Windows does not
+ [fe80::1234:56ff:fe78:9abc%2]:1688. Windows (including cygwin)
+ does not require a scope id unless the same link local address
+ is used on more than one network interface. Windows does not
accept a name and the scope id must be a number.
-P port
- Use TCP port for all subsequent -L statements that do not
+ Use TCP port for all subsequent -L statements that do not
include an optional port. If you use -P and -L, -P must be spec‐
ified before -L.
- -4 and -6
- Used to control the use of IPv4 and IPv4 if you did not use -L.
- If you specify both -4 and -6 or none, vlmcsd uses both proto‐
- cols. If you specify only one, that protocol will be used only.
- These options are deprecated and will be removed.
-
-
- -I This option is deprecated and does nothing. It is provided for
- compatibility with svn681 and earlier versions only. It will be
- removed in a future release.
+ -F0 and -F1
+ Allow (-F1) or disallow (-F0) binding to IP addresses that are
+ currently not configured on your system. The default is -F0. -F1
+ allows you to bind to an IP address that may be configured after
+ you started vlmcsd. vlmcsd will listen on that address as soon
+ as it becomes available. This feature is only available under
+ Linux (IPv4 and IPv6) and FreeBSD (IPv4 only). FreeBSD allows
+ this feature only for the root user (more correctly: processes
+ that have the PRIV_NETINET_BINDANY privilege). Linux does not
+ require a capability for this.
-t seconds
@@ -181,60 +189,54 @@ OPTIONS
often combined with -D.
- -f This flag combines -D and -e. So typing "vlmcsd -f" is identical
- to "vlmcsd -De". The purpose of -f is to provide compatibility
- with previous versions of vlmcsd. This option is deprecated and
- will be removed.
-
-
- -v Use verbose logging. Logs every parameter of the base request
- and the base response. It also logs the HWID of the KMS server
- if KMS protocol version 6 is used. This option is mainly for
- debugging purposes. It only has an effect if some form of log‐
- ging is used. Thus -v does not make sense if not used with -l,
+ -v Use verbose logging. Logs every parameter of the base request
+ and the base response. It also logs the HWID of the KMS server
+ if KMS protocol version 6 is used. This option is mainly for
+ debugging purposes. It only has an effect if some form of log‐
+ ging is used. Thus -v does not make sense if not used with -l,
-e or -f.
- -q Do not use verbose logging. This is actually the default behav‐
+ -q Do not use verbose logging. This is actually the default behav‐
ior. It only makes sense if you use vlmcsd with an ini file (see
- -i and vlmcsd.ini(5)). If the ini file contains the line
+ -i and vlmcsd.ini(5)). If the ini file contains the line
"LogVerbose = true" you can use -q to restore the default behav‐
ior.
-p filename
Create pid file filename. This has nothing to do with KMS ePIDs.
- A pid file is a file where vlmcsd writes its own process id.
- This is used by standard init scripts (typically found in
+ A pid file is a file where vlmcsd writes its own process id.
+ This is used by standard init scripts (typically found in
/etc/init.d). The default is not to write a pid file.
-u user and -g group
- Causes vlmcsd to run in the specified user and group security
- context. The main purpose for this is to drop root privileges
- after it has been started from the root account. To use this
- feature from cygwin you must run cyglsa-config and the account
- from which vlmcsd is started must have the rights "Act as part
- of the operating system" and "Replace a process level token".
+ Causes vlmcsd to run in the specified user and group security
+ context. The main purpose for this is to drop root privileges
+ after it has been started from the root account. To use this
+ feature from cygwin you must run cyglsa-config and the account
+ from which vlmcsd is started must have the rights "Act as part
+ of the operating system" and "Replace a process level token".
The native Windows version does not support these options.
- The actual security context switch is performed after the TCP
- sockets have been created. This allows you to use privileged
+ The actual security context switch is performed after the TCP
+ sockets have been created. This allows you to use privileged
ports (< 1024) when you start vlmcsd from the root account.
However if you use an ini, pid or log file, you must ensure that
- the unprivileged user has access to these files. You can always
- log to syslog(3) from an unprivileged account on most platforms
+ the unprivileged user has access to these files. You can always
+ log to syslog(3) from an unprivileged account on most platforms
(see -l).
-w ePID
- Use ePID as Windows ePID. If specified, -r is disregarded for
+ Use ePID as Windows ePID. If specified, -r is disregarded for
Windows.
-0 ePID
- Use ePID as Office 2010 ePID (including Project and Visio). If
+ Use ePID as Office 2010 ePID (including Project and Visio). If
specified, -r is disregarded for Office 2010.
@@ -244,14 +246,14 @@ OPTIONS
-H HwId
- Use HwId for all products. All HWIDs in the ini file (see -i)
+ Use HwId for all products. All HWIDs in the ini file (see -i)
will not be used. In an ini file you can specify a seperate HWID
- for each application-guid. This is not possible when entering a
+ for each application-guid. This is not possible when entering a
HWID from the command line.
- HwId must be specified as 16 hex digits that are interpreted as
- a series of 8 bytes (big endian). Any character that is not a
- hex digit will be ignored. This is for better readability. The
+ HwId must be specified as 16 hex digits that are interpreted as
+ a series of 8 bytes (big endian). Any character that is not a
+ hex digit will be ignored. This is for better readability. The
following commands are identical:
vlmcsd -H 0123456789ABCDEF
@@ -260,14 +262,14 @@ OPTIONS
-i filename
- Use configuration file (aka ini file) filename. Most configura‐
+ Use configuration file (aka ini file) filename. Most configura‐
tion parameters can be set either via the command line or an ini
- file. The command line always has precedence over configuration
- items in the ini file. See vlmcsd.ini(5) for the format of the
+ file. The command line always has precedence over configuration
+ items in the ini file. See vlmcsd.ini(5) for the format of the
configuration file.
- If vlmcsd has been compiled to use a default configuration file
- (often /etc/vlmcsd.ini), you may use -i- to ignore the default
+ If vlmcsd has been compiled to use a default configuration file
+ (often /etc/vlmcsd.ini), you may use -i- to ignore the default
configuration file.
@@ -280,118 +282,118 @@ OPTIONS
- the file specified by -i does not contain the application-guid
for the KMS request
- -r0 means there are no random ePIDs. vlmcsd simply issues
- default ePIDs that are built into the binary at compile time.
- Pro: behaves like real KMS server that also always issues the
- same ePID. Con: Microsoft may start blacklisting again and the
+ -r0 means there are no random ePIDs. vlmcsd simply issues
+ default ePIDs that are built into the binary at compile time.
+ Pro: behaves like real KMS server that also always issues the
+ same ePID. Con: Microsoft may start blacklisting again and the
default ePID may not work any longer.
- -r1 instructs vlmcsd to generate random ePIDs when the program
+ -r1 instructs vlmcsd to generate random ePIDs when the program
starts or receives a SIGHUP signal and uses these ePIDs until it
- is stopped or receives another SIGHUP. Most other KMS emulators
- generate a new ePID on every KMS request. This is easily
+ is stopped or receives another SIGHUP. Most other KMS emulators
+ generate a new ePID on every KMS request. This is easily
detectable. Microsoft could just modify sppsvc.exe in a way that
- it always sends two identical KMS requests in two RPC requests
- but over the same TCP connection. If both KMS responses contain
- the different ePIDs, the KMS server is not genuine. -r1 is the
- default mode. -r1 also ensures that all three ePIDs (Windows,
- Office 2010 and Office 2013) use the same OS build number and
+ it always sends two identical KMS requests in two RPC requests
+ but over the same TCP connection. If both KMS responses contain
+ the different ePIDs, the KMS server is not genuine. -r1 is the
+ default mode. -r1 also ensures that all three ePIDs (Windows,
+ Office 2010 and Office 2013) use the same OS build number and
LCID (language id).
If vlmcsd has been started by an internet superserver, -r1 works
- identically to -r2. This is simply due to the fact that vlmcsd
+ identically to -r2. This is simply due to the fact that vlmcsd
is started upon a connection request and does not stay in memory
after servicing a KMS request.
- -r2 behaves like most other KMS server emulators with random
- support and generates a new random ePID on every request. Use
- this mode with "care". However since Microsoft currently does
+ -r2 behaves like most other KMS server emulators with random
+ support and generates a new random ePID on every request. Use
+ this mode with "care". However since Microsoft currently does
not seem to do any verification of the ePID, you currently don't
need to pay attention to ePIDs at all.
-C LCID
- Do not randomize the locale id part of the ePID and use LCID
- instead. The LCID must be specified as a decimal number, e.g.
- 1049 for "Russian - Russia". This option has no effect if the
- ePID is not randomized at all, e.g. if it is selected from the
+ Do not randomize the locale id part of the ePID and use LCID
+ instead. The LCID must be specified as a decimal number, e.g.
+ 1049 for "Russian - Russia". This option has no effect if the
+ ePID is not randomized at all, e.g. if it is selected from the
command line or an ini file.
By default vlmcsd generates a valid locale id that is recognized
- by .NET Framework 4.0. This may lead to a locale id which is
+ by .NET Framework 4.0. This may lead to a locale id which is
unlikely to occur in your country, for instance 2155 for "Quecha
- Ecuador". You may want to select the locale id of your country
instead. See MSDN ⟨http://msdn.microsoft.com/en-us/goglobal/
- bb964664.aspx⟩ for a list of valid LCIDs. Please note that some
+ bb964664.aspx⟩ for a list of valid LCIDs. Please note that some
of them are not recognized by .NET Framework 4.0.
- Most other KMS emulators use a fixed LCID of 1033 (English -
+ Most other KMS emulators use a fixed LCID of 1033 (English -
US). To achive the same behavior in vlmcsd use -C 1033.
-R renewal-interval
- Instructs clients to renew activation every renewal-interval.
+ Instructs clients to renew activation every renewal-interval.
The renewal-interval is a number optionally immediately followed
- by a letter indicating the unit. Valid unit letters are s (sec‐
+ by a letter indicating the unit. Valid unit letters are s (sec‐
onds), m (minutes), h (hours), d (days) and w (weeks). If you do
not specify a letter, minutes is assumed.
- -R3d for instance instructs clients to renew activation every 3
+ -R3d for instance instructs clients to renew activation every 3
days. The default renewal-interval is 10080 (identical to 7d and
1w).
Due to poor implementation of Microsofts KMS Client it cannot be
guaranteed that activation is renewed on time as specfied by the
- -R option. Don't care about that. Renewal will happen well
+ -R option. Don't care about that. Renewal will happen well
before your activation expires (usually 180 days).
- Even though you can specify seconds, the granularity of this
- option is 1 minute. Seconds are rounded down to the next multi‐
+ Even though you can specify seconds, the granularity of this
+ option is 1 minute. Seconds are rounded down to the next multi‐
ple of 60.
-A activation-interval
- Instructs clients to retry activation every activation-interval
- if it was unsuccessful, e.g. because it could not reach the
- server. The default is 120 (identical to 2h). activation-inter‐
- val follows the same syntax as renewal-interval in the -R
+ Instructs clients to retry activation every activation-interval
+ if it was unsuccessful, e.g. because it could not reach the
+ server. The default is 120 (identical to 2h). activation-inter‐
+ val follows the same syntax as renewal-interval in the -R
option.
- -s Installs vlmcsd as a Windows service. This option only works
- with the native Windows version and Cygwin. Combine -s with
- other command line options. These will be in effect when you
- start the service. The service automatically starts when you
- reboot your machine. To start it manually, type "net start vlm‐
+ -s Installs vlmcsd as a Windows service. This option only works
+ with the native Windows version and Cygwin. Combine -s with
+ other command line options. These will be in effect when you
+ start the service. The service automatically starts when you
+ reboot your machine. To start it manually, type "net start vlm‐
csd".
- If you use Cygwin, you must include your Cygwin system DLL
- directory (usually C:\Cygwin\bin or C:\Cygwin64\bin) into the
+ If you use Cygwin, you must include your Cygwin system DLL
+ directory (usually C:\Cygwin\bin or C:\Cygwin64\bin) into the
PATH environment variable or the service will not start.
- You can reinstall the service anytime using vlmcsd -s again,
- e.g. with a different command line. If the service is running,
+ You can reinstall the service anytime using vlmcsd -s again,
+ e.g. with a different command line. If the service is running,
it will be restarted with the new command line.
- When using -s the command line is checked for basic syntax
+ When using -s the command line is checked for basic syntax
errors only. For example "vlmcsd -s -L 1.2.3.4" reports no error
- but the service will not start if 1.2.3.4 is not an IP address
+ but the service will not start if 1.2.3.4 is not an IP address
on your system.
- -S Uninstalls the vlmcsd service. Works only with the native Win‐
- dows version and Cygwin. All other options will be ignored if
+ -S Uninstalls the vlmcsd service. Works only with the native Win‐
+ dows version and Cygwin. All other options will be ignored if
you include -S in the command line.
-U [domain\]username
- Can only be used together with -s. Starts the service as a dif‐
- ferent user than the local SYSTEM account. This is used to run
- the service under an account with low privileges. If you omit
+ Can only be used together with -s. Starts the service as a dif‐
+ ferent user than the local SYSTEM account. This is used to run
+ the service under an account with low privileges. If you omit
the domain, an account from the local computer will be used.
You may use "NT AUTHORITY\NetworkService". This is a pseudo user
- with low privileges. You may also use "NT AUTHORITY\LocalSer‐
+ with low privileges. You may also use "NT AUTHORITY\LocalSer‐
vice" which has more privileges but these are of no use for run‐
ning vlmcsd.
@@ -399,20 +401,20 @@ OPTIONS
sion for your executable. "NT AUTHORITY\NetworkService" normally
has no permission to run binaries from your home directory.
- For your convenience you can use the special username "/l" as a
+ For your convenience you can use the special username "/l" as a
shortcut for "NT AUTHORITY\LocalService" and "/n" for "NT
- AUTHORITY\NetworkService". "vlmcsd -s -U /n" installs the ser‐
+ AUTHORITY\NetworkService". "vlmcsd -s -U /n" installs the ser‐
vice to run as "NT AUTHORITY\NetworkService".
-W password
- Can only be used together with -s. Specifies a password for the
- corresponding username you use with -U. SYSTEM, "NT AUTHOR‐
- ITY\NetworkService", "NT AUTHORITY\LocalService" do not require
+ Can only be used together with -s. Specifies a password for the
+ corresponding username you use with -U. SYSTEM, "NT AUTHOR‐
+ ITY\NetworkService", "NT AUTHORITY\LocalService" do not require
a password.
- If you specify a user with even lower privileges than "NT
- AUTHORITY\NetworkService", you must specify its password. You
+ If you specify a user with even lower privileges than "NT
+ AUTHORITY\NetworkService", you must specify its password. You
also have to grant the "Log on as a service" right to that user.
@@ -421,50 +423,50 @@ SIGNALS
SIGTERM, SIGINT
- These signals cause vlmcsd to exit gracefully. All global sema‐
- phores and shared memory pages will be released, the pid file
- will be unlinked (deleted) and a shutdown message will be
+ These signals cause vlmcsd to exit gracefully. All global sema‐
+ phores and shared memory pages will be released, the pid file
+ will be unlinked (deleted) and a shutdown message will be
logged.
- SIGHUP Causes vlmcsd to be restarted completely. This is useful if you
- started vlmcsd with an ini file. You can modify the ini file
- while vlmcsd is running and then sending SIGHUP, e.g. by typing
- "killall -SIGHUP vlmcsd" or "kill -SIGHUP `cat /var/run/vlm‐
+ SIGHUP Causes vlmcsd to be restarted completely. This is useful if you
+ started vlmcsd with an ini file. You can modify the ini file
+ while vlmcsd is running and then sending SIGHUP, e.g. by typing
+ "killall -SIGHUP vlmcsd" or "kill -SIGHUP `cat /var/run/vlm‐
csd.pid`".
The SIGHUP handler has been implemented relatively simple. It is
- virtually the same as stopping vlmcsd and starting it again
+ virtually the same as stopping vlmcsd and starting it again
immediately with the following exceptions:
— The new process does not get a new process id.
- — If you used a pid file, it is not deleted and recreated
+ — If you used a pid file, it is not deleted and recreated
because the process id stays the same.
- — If you used the 'user' and/or 'group' directive in an ini
- file these are ignored. This is because once you switched to
+ — If you used the 'user' and/or 'group' directive in an ini
+ file these are ignored. This is because once you switched to
lower privileged users and groups, there is no way back. Any‐
thing else would be a severe security flaw in the OS.
- Signaling is not available in the native Windows version and in the
+ Signaling is not available in the native Windows version and in the
Cygwin version when it runs as Windows service.
SUPPORTED OPERATING SYSTEMS
- vlmcsd 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
+ vlmcsd 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.
SUPPORTED PRODUCTS
- vlmcsd can answer activation requests for the following products: Win‐
- dows Vista, Windows 7, Windows 8, Windows 8.1, Windows 10, Windows
- Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows
- Server 2012 R2, Office 2010, Project 2010, Visio 2010, Office 2013,
+ vlmcsd can answer activation requests for the following products: Win‐
+ dows Vista, Windows 7, Windows 8, Windows 8.1, Windows 10, Windows
+ Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows
+ Server 2012 R2, Office 2010, Project 2010, Visio 2010, Office 2013,
Project 2013, Visio 2013, Office 2016, Project 2016, Visio 2016.
Office, Project and Visio must be volume license versions.
@@ -476,24 +478,24 @@ FILES
EXAMPLES
vlmcsd -f
- Starts vlmcsd in foreground. Useful if you use it for the first
- time and want to see what's happening when a client requests
+ Starts vlmcsd in foreground. Useful if you use it for the first
+ time and want to see what's happening when a client requests
activation.
vlmcsd -l /var/log/vlmcsd.log
- Starts vlmcsd as a daemon and logs everything to /var/log/vlm‐
+ Starts vlmcsd as a daemon and logs everything to /var/log/vlm‐
csd.log.
vlmcsd -L 192.168.1.17
Starts vlmcsd as a daemon and listens on IP address 192.168.1.17
- only. This is useful for routers that have a public and a pri‐
+ only. This is useful for routers that have a public and a pri‐
vate IP address to prevent your KMS server from becoming public.
vlmcsd -s -U /n -l C:\logs\vlmcsd.log
- Installs vlmcsd as a Windows service with low privileges and
+ Installs vlmcsd as a Windows service with low privileges and
logs everything to C:\logs\vlmcsd.log when the service is
started with "net start vlmcsd".
@@ -501,18 +503,18 @@ EXAMPLES
BUGS
An ePID specified in an ini file must not contain spaces.
- The maximum number of -L options in the command line or listen state‐
+ The maximum number of -L options in the command line or listen state‐
ments in the inifile is the platform default for FD_SETSIZE. This is 64
on Windows and 1024 on most Unixes.
AUTHOR
- Written by crony12, Hotbird64 and vityan666. With contributions from
+ Written by crony12, Hotbird64 and vityan666. With contributions from
DougQaid.
CREDITS
- Thanks to CODYQX4, deagles, eIcn, mikmik38, nosferati87, qad, Rati‐
+ Thanks to CODYQX4, deagles, eIcn, mikmik38, nosferati87, qad, Rati‐
borus, ...
@@ -521,4 +523,4 @@ SEE ALSO
-Hotbird64 September 2015 VLMCSD(8)
+Hotbird64 June 2016 VLMCSD(8)
diff --git a/vlmcsd.8.html b/vlmcsd.8.html
index 2f98b9a..c2b55e7 100644
--- a/vlmcsd.8.html
+++ b/vlmcsd.8.html
@@ -1,5 +1,5 @@
-
+
@@ -112,6 +112,27 @@ is optional. Thus "vlmcsd -r 2" and "vlmcsd
Displays help.
+
+
+ |
+
+
+
+ -V |
+ |
+
+
+
+ Displays extended version information. This includes the
+compiler used to build vlmcsd, the intended platform and
+flags (compile time options) to build vlmcsd. If you have
+the source code of vlmcsd, you can type make help (or
+gmake help on systems that do not use the GNU version
+of make(1) by default) to see the meaning of those
+flags. |
+
+
-L
ipaddress[:port]
@@ -149,30 +170,19 @@ subsequent -L statements that do not include an
optional port. If you use -P and -L, -P
must be specified before -L.
--4 and -6
+-F0 and -F1
-Used to control the use of IPv4
-and IPv4 if you did not use -L. If you specify both
--4 and -6 or none, vlmcsd uses both protocols.
-If you specify only one, that protocol will be used only.
-These options are deprecated and will be removed.
-
-
-
- |
-
-
-
- -I |
- |
-
-
-
- This option is deprecated and does nothing. It is
-provided for compatibility with svn681 and earlier versions
-only. It will be removed in a future release. |
-
+Allow (-F1) or disallow
+(-F0) binding to IP addresses that are currently not
+configured on your system. The default is -F0.
+-F1 allows you to bind to an IP address that may be
+configured after you started vlmcsd. vlmcsd
+will listen on that address as soon as it becomes available.
+This feature is only available under Linux (IPv4 and IPv6)
+and FreeBSD (IPv4 only). FreeBSD allows this feature only
+for the root user (more correctly: processes that have the
+PRIV_NETINET_BINDANY privilege). Linux does not require a
+capability for this.
-t seconds
@@ -321,21 +331,6 @@ combined with -D. |
- -f |
- |
-
-
-
- This flag combines -D and -e. So typing
-"vlmcsd -f" is identical to "vlmcsd
--De". The purpose of -f is to provide
-compatibility with previous versions of vlmcsd. This
-option is deprecated and will be removed. |
-
- |
-
-
-
-v |
|
diff --git a/vlmcsd.8.pdf b/vlmcsd.8.pdf
index 6741219..82a410c 100644
Binary files a/vlmcsd.8.pdf and b/vlmcsd.8.pdf differ
diff --git a/vlmcsd.8.unix.txt b/vlmcsd.8.unix.txt
index d8ea808..c569bb4 100644
--- a/vlmcsd.8.unix.txt
+++ b/vlmcsd.8.unix.txt
@@ -52,46 +52,54 @@ OPTIONS
Displays help.
+ -V Displays extended version information. This includes the com‐
+ piler used to build vlmcsd, the intended platform and flags
+ (compile time options) to build vlmcsd. If you have the source
+ code of vlmcsd, you can type make help (or gmake help on systems
+ that do not use the GNU version of make(1) by default) to see
+ the meaning of those flags.
+
+
-L ipaddress[:port]
- Instructs vlmcsd to listen on ipaddress with optional port
- (default 1688). You can use this option more than once. If you
+ Instructs vlmcsd to listen on ipaddress with optional port
+ (default 1688). You can use this option more than once. If you
do not specify -L at least once, IP addresses 0.0.0.0 (IPv4) and
:: (IPv6) are used. If the IP address contains colons (IPv6) you
- must enclose the IP address in brackets if you specify the
+ must enclose the IP address in brackets if you specify the
optional port, e.g. [2001:db8::dead:beef]:1688.
- If no port is specified, vlmcsd uses the default port according
- to a preceding -P option. If you specify a port, it can be a
- number (1-65535) or a name (usually found in /etc/services if
+ If no port is specified, vlmcsd uses the default port according
+ to a preceding -P option. If you specify a port, it can be a
+ number (1-65535) or a name (usually found in /etc/services if
not provided via LDAP, NIS+ or another name service).
- If you specify a link local IPv6 address (fe80::/10, usually
+ If you specify a link local IPv6 address (fe80::/10, usually
starting with fe80::), it must be followed by a percent sign (%)
- and a scope id (=network interface name or number) on most
- unixoid OSses including Linux, Android, MacOS X and iOS, e.g.
+ and a scope id (=network interface name or number) on most
+ unixoid OSses including Linux, Android, MacOS X and iOS, e.g.
fe80::1234:56ff:fe78:9abc%eth0 or
- [fe80::1234:56ff:fe78:9abc%2]:1688. Windows (including cygwin)
- does not require a scope id unless the same link local address
- is used on more than one network interface. Windows does not
+ [fe80::1234:56ff:fe78:9abc%2]:1688. Windows (including cygwin)
+ does not require a scope id unless the same link local address
+ is used on more than one network interface. Windows does not
accept a name and the scope id must be a number.
-P port
- Use TCP port for all subsequent -L statements that do not
+ Use TCP port for all subsequent -L statements that do not
include an optional port. If you use -P and -L, -P must be spec‐
ified before -L.
- -4 and -6
- Used to control the use of IPv4 and IPv4 if you did not use -L.
- If you specify both -4 and -6 or none, vlmcsd uses both proto‐
- cols. If you specify only one, that protocol will be used only.
- These options are deprecated and will be removed.
-
-
- -I This option is deprecated and does nothing. It is provided for
- compatibility with svn681 and earlier versions only. It will be
- removed in a future release.
+ -F0 and -F1
+ Allow (-F1) or disallow (-F0) binding to IP addresses that are
+ currently not configured on your system. The default is -F0. -F1
+ allows you to bind to an IP address that may be configured after
+ you started vlmcsd. vlmcsd will listen on that address as soon
+ as it becomes available. This feature is only available under
+ Linux (IPv4 and IPv6) and FreeBSD (IPv4 only). FreeBSD allows
+ this feature only for the root user (more correctly: processes
+ that have the PRIV_NETINET_BINDANY privilege). Linux does not
+ require a capability for this.
-t seconds
@@ -181,60 +189,54 @@ OPTIONS
often combined with -D.
- -f This flag combines -D and -e. So typing "vlmcsd -f" is identical
- to "vlmcsd -De". The purpose of -f is to provide compatibility
- with previous versions of vlmcsd. This option is deprecated and
- will be removed.
-
-
- -v Use verbose logging. Logs every parameter of the base request
- and the base response. It also logs the HWID of the KMS server
- if KMS protocol version 6 is used. This option is mainly for
- debugging purposes. It only has an effect if some form of log‐
- ging is used. Thus -v does not make sense if not used with -l,
+ -v Use verbose logging. Logs every parameter of the base request
+ and the base response. It also logs the HWID of the KMS server
+ if KMS protocol version 6 is used. This option is mainly for
+ debugging purposes. It only has an effect if some form of log‐
+ ging is used. Thus -v does not make sense if not used with -l,
-e or -f.
- -q Do not use verbose logging. This is actually the default behav‐
+ -q Do not use verbose logging. This is actually the default behav‐
ior. It only makes sense if you use vlmcsd with an ini file (see
- -i and vlmcsd.ini(5)). If the ini file contains the line
+ -i and vlmcsd.ini(5)). If the ini file contains the line
"LogVerbose = true" you can use -q to restore the default behav‐
ior.
-p filename
Create pid file filename. This has nothing to do with KMS ePIDs.
- A pid file is a file where vlmcsd writes its own process id.
- This is used by standard init scripts (typically found in
+ A pid file is a file where vlmcsd writes its own process id.
+ This is used by standard init scripts (typically found in
/etc/init.d). The default is not to write a pid file.
-u user and -g group
- Causes vlmcsd to run in the specified user and group security
- context. The main purpose for this is to drop root privileges
- after it has been started from the root account. To use this
- feature from cygwin you must run cyglsa-config and the account
- from which vlmcsd is started must have the rights "Act as part
- of the operating system" and "Replace a process level token".
+ Causes vlmcsd to run in the specified user and group security
+ context. The main purpose for this is to drop root privileges
+ after it has been started from the root account. To use this
+ feature from cygwin you must run cyglsa-config and the account
+ from which vlmcsd is started must have the rights "Act as part
+ of the operating system" and "Replace a process level token".
The native Windows version does not support these options.
- The actual security context switch is performed after the TCP
- sockets have been created. This allows you to use privileged
+ The actual security context switch is performed after the TCP
+ sockets have been created. This allows you to use privileged
ports (< 1024) when you start vlmcsd from the root account.
However if you use an ini, pid or log file, you must ensure that
- the unprivileged user has access to these files. You can always
- log to syslog(3) from an unprivileged account on most platforms
+ the unprivileged user has access to these files. You can always
+ log to syslog(3) from an unprivileged account on most platforms
(see -l).
-w ePID
- Use ePID as Windows ePID. If specified, -r is disregarded for
+ Use ePID as Windows ePID. If specified, -r is disregarded for
Windows.
-0 ePID
- Use ePID as Office 2010 ePID (including Project and Visio). If
+ Use ePID as Office 2010 ePID (including Project and Visio). If
specified, -r is disregarded for Office 2010.
@@ -244,14 +246,14 @@ OPTIONS
-H HwId
- Use HwId for all products. All HWIDs in the ini file (see -i)
+ Use HwId for all products. All HWIDs in the ini file (see -i)
will not be used. In an ini file you can specify a seperate HWID
- for each application-guid. This is not possible when entering a
+ for each application-guid. This is not possible when entering a
HWID from the command line.
- HwId must be specified as 16 hex digits that are interpreted as
- a series of 8 bytes (big endian). Any character that is not a
- hex digit will be ignored. This is for better readability. The
+ HwId must be specified as 16 hex digits that are interpreted as
+ a series of 8 bytes (big endian). Any character that is not a
+ hex digit will be ignored. This is for better readability. The
following commands are identical:
vlmcsd -H 0123456789ABCDEF
@@ -260,14 +262,14 @@ OPTIONS
-i filename
- Use configuration file (aka ini file) filename. Most configura‐
+ Use configuration file (aka ini file) filename. Most configura‐
tion parameters can be set either via the command line or an ini
- file. The command line always has precedence over configuration
- items in the ini file. See vlmcsd.ini(5) for the format of the
+ file. The command line always has precedence over configuration
+ items in the ini file. See vlmcsd.ini(5) for the format of the
configuration file.
- If vlmcsd has been compiled to use a default configuration file
- (often /etc/vlmcsd.ini), you may use -i- to ignore the default
+ If vlmcsd has been compiled to use a default configuration file
+ (often /etc/vlmcsd.ini), you may use -i- to ignore the default
configuration file.
@@ -280,118 +282,118 @@ OPTIONS
- the file specified by -i does not contain the application-guid
for the KMS request
- -r0 means there are no random ePIDs. vlmcsd simply issues
- default ePIDs that are built into the binary at compile time.
- Pro: behaves like real KMS server that also always issues the
- same ePID. Con: Microsoft may start blacklisting again and the
+ -r0 means there are no random ePIDs. vlmcsd simply issues
+ default ePIDs that are built into the binary at compile time.
+ Pro: behaves like real KMS server that also always issues the
+ same ePID. Con: Microsoft may start blacklisting again and the
default ePID may not work any longer.
- -r1 instructs vlmcsd to generate random ePIDs when the program
+ -r1 instructs vlmcsd to generate random ePIDs when the program
starts or receives a SIGHUP signal and uses these ePIDs until it
- is stopped or receives another SIGHUP. Most other KMS emulators
- generate a new ePID on every KMS request. This is easily
+ is stopped or receives another SIGHUP. Most other KMS emulators
+ generate a new ePID on every KMS request. This is easily
detectable. Microsoft could just modify sppsvc.exe in a way that
- it always sends two identical KMS requests in two RPC requests
- but over the same TCP connection. If both KMS responses contain
- the different ePIDs, the KMS server is not genuine. -r1 is the
- default mode. -r1 also ensures that all three ePIDs (Windows,
- Office 2010 and Office 2013) use the same OS build number and
+ it always sends two identical KMS requests in two RPC requests
+ but over the same TCP connection. If both KMS responses contain
+ the different ePIDs, the KMS server is not genuine. -r1 is the
+ default mode. -r1 also ensures that all three ePIDs (Windows,
+ Office 2010 and Office 2013) use the same OS build number and
LCID (language id).
If vlmcsd has been started by an internet superserver, -r1 works
- identically to -r2. This is simply due to the fact that vlmcsd
+ identically to -r2. This is simply due to the fact that vlmcsd
is started upon a connection request and does not stay in memory
after servicing a KMS request.
- -r2 behaves like most other KMS server emulators with random
- support and generates a new random ePID on every request. Use
- this mode with "care". However since Microsoft currently does
+ -r2 behaves like most other KMS server emulators with random
+ support and generates a new random ePID on every request. Use
+ this mode with "care". However since Microsoft currently does
not seem to do any verification of the ePID, you currently don't
need to pay attention to ePIDs at all.
-C LCID
- Do not randomize the locale id part of the ePID and use LCID
- instead. The LCID must be specified as a decimal number, e.g.
- 1049 for "Russian - Russia". This option has no effect if the
- ePID is not randomized at all, e.g. if it is selected from the
+ Do not randomize the locale id part of the ePID and use LCID
+ instead. The LCID must be specified as a decimal number, e.g.
+ 1049 for "Russian - Russia". This option has no effect if the
+ ePID is not randomized at all, e.g. if it is selected from the
command line or an ini file.
By default vlmcsd generates a valid locale id that is recognized
- by .NET Framework 4.0. This may lead to a locale id which is
+ by .NET Framework 4.0. This may lead to a locale id which is
unlikely to occur in your country, for instance 2155 for "Quecha
- Ecuador". You may want to select the locale id of your country
instead. See MSDN ⟨http://msdn.microsoft.com/en-us/goglobal/
- bb964664.aspx⟩ for a list of valid LCIDs. Please note that some
+ bb964664.aspx⟩ for a list of valid LCIDs. Please note that some
of them are not recognized by .NET Framework 4.0.
- Most other KMS emulators use a fixed LCID of 1033 (English -
+ Most other KMS emulators use a fixed LCID of 1033 (English -
US). To achive the same behavior in vlmcsd use -C 1033.
-R renewal-interval
- Instructs clients to renew activation every renewal-interval.
+ Instructs clients to renew activation every renewal-interval.
The renewal-interval is a number optionally immediately followed
- by a letter indicating the unit. Valid unit letters are s (sec‐
+ by a letter indicating the unit. Valid unit letters are s (sec‐
onds), m (minutes), h (hours), d (days) and w (weeks). If you do
not specify a letter, minutes is assumed.
- -R3d for instance instructs clients to renew activation every 3
+ -R3d for instance instructs clients to renew activation every 3
days. The default renewal-interval is 10080 (identical to 7d and
1w).
Due to poor implementation of Microsofts KMS Client it cannot be
guaranteed that activation is renewed on time as specfied by the
- -R option. Don't care about that. Renewal will happen well
+ -R option. Don't care about that. Renewal will happen well
before your activation expires (usually 180 days).
- Even though you can specify seconds, the granularity of this
- option is 1 minute. Seconds are rounded down to the next multi‐
+ Even though you can specify seconds, the granularity of this
+ option is 1 minute. Seconds are rounded down to the next multi‐
ple of 60.
-A activation-interval
- Instructs clients to retry activation every activation-interval
- if it was unsuccessful, e.g. because it could not reach the
- server. The default is 120 (identical to 2h). activation-inter‐
- val follows the same syntax as renewal-interval in the -R
+ Instructs clients to retry activation every activation-interval
+ if it was unsuccessful, e.g. because it could not reach the
+ server. The default is 120 (identical to 2h). activation-inter‐
+ val follows the same syntax as renewal-interval in the -R
option.
- -s Installs vlmcsd as a Windows service. This option only works
- with the native Windows version and Cygwin. Combine -s with
- other command line options. These will be in effect when you
- start the service. The service automatically starts when you
- reboot your machine. To start it manually, type "net start vlm‐
+ -s Installs vlmcsd as a Windows service. This option only works
+ with the native Windows version and Cygwin. Combine -s with
+ other command line options. These will be in effect when you
+ start the service. The service automatically starts when you
+ reboot your machine. To start it manually, type "net start vlm‐
csd".
- If you use Cygwin, you must include your Cygwin system DLL
- directory (usually C:\Cygwin\bin or C:\Cygwin64\bin) into the
+ If you use Cygwin, you must include your Cygwin system DLL
+ directory (usually C:\Cygwin\bin or C:\Cygwin64\bin) into the
PATH environment variable or the service will not start.
- You can reinstall the service anytime using vlmcsd -s again,
- e.g. with a different command line. If the service is running,
+ You can reinstall the service anytime using vlmcsd -s again,
+ e.g. with a different command line. If the service is running,
it will be restarted with the new command line.
- When using -s the command line is checked for basic syntax
+ When using -s the command line is checked for basic syntax
errors only. For example "vlmcsd -s -L 1.2.3.4" reports no error
- but the service will not start if 1.2.3.4 is not an IP address
+ but the service will not start if 1.2.3.4 is not an IP address
on your system.
- -S Uninstalls the vlmcsd service. Works only with the native Win‐
- dows version and Cygwin. All other options will be ignored if
+ -S Uninstalls the vlmcsd service. Works only with the native Win‐
+ dows version and Cygwin. All other options will be ignored if
you include -S in the command line.
-U [domain\]username
- Can only be used together with -s. Starts the service as a dif‐
- ferent user than the local SYSTEM account. This is used to run
- the service under an account with low privileges. If you omit
+ Can only be used together with -s. Starts the service as a dif‐
+ ferent user than the local SYSTEM account. This is used to run
+ the service under an account with low privileges. If you omit
the domain, an account from the local computer will be used.
You may use "NT AUTHORITY\NetworkService". This is a pseudo user
- with low privileges. You may also use "NT AUTHORITY\LocalSer‐
+ with low privileges. You may also use "NT AUTHORITY\LocalSer‐
vice" which has more privileges but these are of no use for run‐
ning vlmcsd.
@@ -399,20 +401,20 @@ OPTIONS
sion for your executable. "NT AUTHORITY\NetworkService" normally
has no permission to run binaries from your home directory.
- For your convenience you can use the special username "/l" as a
+ For your convenience you can use the special username "/l" as a
shortcut for "NT AUTHORITY\LocalService" and "/n" for "NT
- AUTHORITY\NetworkService". "vlmcsd -s -U /n" installs the ser‐
+ AUTHORITY\NetworkService". "vlmcsd -s -U /n" installs the ser‐
vice to run as "NT AUTHORITY\NetworkService".
-W password
- Can only be used together with -s. Specifies a password for the
- corresponding username you use with -U. SYSTEM, "NT AUTHOR‐
- ITY\NetworkService", "NT AUTHORITY\LocalService" do not require
+ Can only be used together with -s. Specifies a password for the
+ corresponding username you use with -U. SYSTEM, "NT AUTHOR‐
+ ITY\NetworkService", "NT AUTHORITY\LocalService" do not require
a password.
- If you specify a user with even lower privileges than "NT
- AUTHORITY\NetworkService", you must specify its password. You
+ If you specify a user with even lower privileges than "NT
+ AUTHORITY\NetworkService", you must specify its password. You
also have to grant the "Log on as a service" right to that user.
@@ -421,50 +423,50 @@ SIGNALS
SIGTERM, SIGINT
- These signals cause vlmcsd to exit gracefully. All global sema‐
- phores and shared memory pages will be released, the pid file
- will be unlinked (deleted) and a shutdown message will be
+ These signals cause vlmcsd to exit gracefully. All global sema‐
+ phores and shared memory pages will be released, the pid file
+ will be unlinked (deleted) and a shutdown message will be
logged.
- SIGHUP Causes vlmcsd to be restarted completely. This is useful if you
- started vlmcsd with an ini file. You can modify the ini file
- while vlmcsd is running and then sending SIGHUP, e.g. by typing
- "killall -SIGHUP vlmcsd" or "kill -SIGHUP `cat /var/run/vlm‐
+ SIGHUP Causes vlmcsd to be restarted completely. This is useful if you
+ started vlmcsd with an ini file. You can modify the ini file
+ while vlmcsd is running and then sending SIGHUP, e.g. by typing
+ "killall -SIGHUP vlmcsd" or "kill -SIGHUP `cat /var/run/vlm‐
csd.pid`".
The SIGHUP handler has been implemented relatively simple. It is
- virtually the same as stopping vlmcsd and starting it again
+ virtually the same as stopping vlmcsd and starting it again
immediately with the following exceptions:
— The new process does not get a new process id.
- — If you used a pid file, it is not deleted and recreated
+ — If you used a pid file, it is not deleted and recreated
because the process id stays the same.
- — If you used the 'user' and/or 'group' directive in an ini
- file these are ignored. This is because once you switched to
+ — If you used the 'user' and/or 'group' directive in an ini
+ file these are ignored. This is because once you switched to
lower privileged users and groups, there is no way back. Any‐
thing else would be a severe security flaw in the OS.
- Signaling is not available in the native Windows version and in the
+ Signaling is not available in the native Windows version and in the
Cygwin version when it runs as Windows service.
SUPPORTED OPERATING SYSTEMS
- vlmcsd 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
+ vlmcsd 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.
SUPPORTED PRODUCTS
- vlmcsd can answer activation requests for the following products: Win‐
- dows Vista, Windows 7, Windows 8, Windows 8.1, Windows 10, Windows
- Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows
- Server 2012 R2, Office 2010, Project 2010, Visio 2010, Office 2013,
+ vlmcsd can answer activation requests for the following products: Win‐
+ dows Vista, Windows 7, Windows 8, Windows 8.1, Windows 10, Windows
+ Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows
+ Server 2012 R2, Office 2010, Project 2010, Visio 2010, Office 2013,
Project 2013, Visio 2013, Office 2016, Project 2016, Visio 2016.
Office, Project and Visio must be volume license versions.
@@ -476,24 +478,24 @@ FILES
EXAMPLES
vlmcsd -f
- Starts vlmcsd in foreground. Useful if you use it for the first
- time and want to see what's happening when a client requests
+ Starts vlmcsd in foreground. Useful if you use it for the first
+ time and want to see what's happening when a client requests
activation.
vlmcsd -l /var/log/vlmcsd.log
- Starts vlmcsd as a daemon and logs everything to /var/log/vlm‐
+ Starts vlmcsd as a daemon and logs everything to /var/log/vlm‐
csd.log.
vlmcsd -L 192.168.1.17
Starts vlmcsd as a daemon and listens on IP address 192.168.1.17
- only. This is useful for routers that have a public and a pri‐
+ only. This is useful for routers that have a public and a pri‐
vate IP address to prevent your KMS server from becoming public.
vlmcsd -s -U /n -l C:\logs\vlmcsd.log
- Installs vlmcsd as a Windows service with low privileges and
+ Installs vlmcsd as a Windows service with low privileges and
logs everything to C:\logs\vlmcsd.log when the service is
started with "net start vlmcsd".
@@ -501,18 +503,18 @@ EXAMPLES
BUGS
An ePID specified in an ini file must not contain spaces.
- The maximum number of -L options in the command line or listen state‐
+ The maximum number of -L options in the command line or listen state‐
ments in the inifile is the platform default for FD_SETSIZE. This is 64
on Windows and 1024 on most Unixes.
AUTHOR
- Written by crony12, Hotbird64 and vityan666. With contributions from
+ Written by crony12, Hotbird64 and vityan666. With contributions from
DougQaid.
CREDITS
- Thanks to CODYQX4, deagles, eIcn, mikmik38, nosferati87, qad, Rati‐
+ Thanks to CODYQX4, deagles, eIcn, mikmik38, nosferati87, qad, Rati‐
borus, ...
@@ -521,4 +523,4 @@ SEE ALSO
-Hotbird64 September 2015 VLMCSD(8)
+Hotbird64 June 2016 VLMCSD(8)
diff --git a/vlmcsd.c b/vlmcsd.c
index 63ef423..1c4f3fb 100644
--- a/vlmcsd.c
+++ b/vlmcsd.c
@@ -7,6 +7,10 @@
#error Microsoft RPC is only available on Windows and Cygwin
#endif
+#if defined(USE_MSRPC) && defined(SIMPLE_SOCKETS)
+#error You can only define either USE_MSRPC or SIMPLE_SOCKETS but not both
+#endif
+
#if defined(NO_SOCKETS) && defined(USE_MSRPC)
#error Cannot use inetd mode with Microsoft RPC
#endif
@@ -66,18 +70,20 @@
#include "ntservice.h"
#include "helpers.h"
+#ifdef ENABLE_DEPRECATED_OPTIONS
+static const char* const optstring = "N:B:m:t:w:0:3:H:A:R:u:g:L:p:i:P:l:r:U:W:C:F:SsfeDd46VvIqkZ";
+#else // !ENABLE_DEPRECATED_OPTIONS
+static const char* const optstring = "N:B:m:t:w:0:3:H:A:R:u:g:L:p:i:P:l:r:U:W:C:F:SseDdVvqkZ";
+#endif // !ENABLE_DEPRECATED_OPTIONS
-static const char* const optstring = "N:B:m:t:w:0:3:H:A:R:u:g:L:p:i:P:l:r:U:W:C:SsfeDd46VvIdqkZ";
-
-#if !defined(NO_SOCKETS)
-#if !defined(USE_MSRPC)
+#if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
static uint_fast8_t maxsockets = 0;
-static int_fast8_t haveIPv6Stack = 0;
-static int_fast8_t haveIPv4Stack = 0;
+
+#ifdef ENABLE_DEPRECATED_OPTIONS
static int_fast8_t v6required = 0;
static int_fast8_t v4required = 0;
-#endif // !defined(USE_MSRPC)
-#endif // !defined(NO_SOCKETS)
+#endif // ENABLE_DEPRECATED_OPTIONS
+#endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
#ifdef _NTSERVICE
static int_fast8_t installService = 0;
@@ -107,11 +113,16 @@ static IniFileParameter_t IniFileParameterList[] =
{ "RandomizationLevel", INI_PARAM_RANDOMIZATION_LEVEL },
{ "LCID", INI_PARAM_LCID },
# endif // NO_RANDOM_EPID
-# ifdef USE_MSRPC
+# if !defined(NO_SOCKETS) && (defined(USE_MSRPC) || defined(SIMPLE_SOCKETS))
{ "Port", INI_PARAM_PORT },
-# endif // USE_MSRPC
+# endif // defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)
# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
+# ifndef SIMPLE_SOCKETS
{ "Listen", INI_PARAM_LISTEN },
+# endif // SIMPLE_SOCKETS
+# if HAVE_FREEBIND
+ { "FreeBind", INI_PARAM_FREEBIND },
+# endif // HAVE_FREEBIND
# if !defined(NO_LIMIT) && !__minix__
{ "MaxWorkers", INI_PARAM_MAX_WORKERS },
# endif // !defined(NO_LIMIT) && !__minix__
@@ -200,10 +211,10 @@ static char GetNumericId(gid_t *restrict id, const char *const c)
gid_t temp;
temp = (gid_t)strtoll(c, &endptr, 10);
-
if (!*endptr) *id = temp;
+ if (*endptr || temp == (gid_t)-1) errno = EINVAL;
- return *endptr;
+ return *endptr || *id == (gid_t)-1;
}
@@ -267,14 +278,15 @@ static __noreturn void usage()
" -C \t\tuse fixed in random ePIDs\n"
#endif // NO_RANDOM_EPID
#ifndef NO_SOCKETS
- #ifndef USE_MSRPC
- " -4\t\t\tuse IPv4\n"
- " -6\t\t\tuse IPv6\n"
+ #if !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
" -L [:]\tlisten on IP address with optional \n"
" -P \t\tset TCP port for subsequent -L statements (default 1688)\n"
- #else // USE_MSRPC
+ #if HAVE_FREEBIND
+ " -F0, -F1\t\tdisable/enable binding to foreign IP addresses\n"
+ #endif // HAVE_FREEBIND
+ #else // defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)
" -P \t\tuse TCP port (default 1688)\n"
- #endif // USE_MSRPC
+ #endif // defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)
#if !defined(NO_LIMIT) && !__minix__
" -m \t\tHandle max. simultaneously (default no limit)\n"
#endif // !defined(NO_LIMIT) && !__minix__
@@ -293,11 +305,8 @@ static __noreturn void usage()
#endif // NO_LOG
#ifndef _WIN32 //
" -D run in foreground\n"
- " -f run in foreground"
- #ifndef NO_LOG
- " and log to stdout"
- #endif // NO_LOG
- "\n"
+ #else // _WIN32
+ " -D does nothing. Provided for compatibility with POSIX versions only\n"
#endif // _WIN32
#endif // NO_SOCKETS
#ifndef USE_MSRPC
@@ -329,8 +338,10 @@ static __noreturn void usage()
" -q\t\t\tdon't log verbose (default)\n"
#endif // NO_VERBOSE_LOG
#endif // NO_LOG
- " -V display version information and exit"
- "\n",
+ #ifndef NO_VERSION_INFORMATION
+ " -V display version information and exit\n"
+ #endif // NO_VERSION_INFORMATION
+ ,
Version, global_argv[0]);
exit(!0);
@@ -507,20 +518,21 @@ static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
# endif // NO_RANDOM_EPID
-# ifdef USE_MSRPC
+# if (defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)) && !defined(NO_SOCKETS)
case INI_PARAM_PORT:
defaultport = allocateStringArgument(iniarg);
break;
-# endif // USE_MSRPC
+# endif // (defined(USE_MSRPC) || defined(SIMPLE_SOCKETS)) && !defined(NO_SOCKETS
-# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
+# if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
case INI_PARAM_LISTEN:
maxsockets++;
return TRUE;
+# endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
# if !defined(NO_LIMIT) && !__minix__
case INI_PARAM_MAX_WORKERS:
@@ -532,7 +544,6 @@ static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
break;
# endif // !defined(NO_LIMIT) && !__minix__
-# endif // NO_SOCKETS
# ifndef NO_PID_FILE
@@ -593,6 +604,14 @@ static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
# endif // USE_MSRPC
+# if HAVE_FREEBIND
+
+ case INI_PARAM_FREEBIND:
+ success = getIniFileArgumentBool(&freebind, iniarg);
+ break;
+
+# endif // HAVE_FREEBIND
+
default:
return FALSE;
}
@@ -729,7 +748,7 @@ static BOOL handleIniFileParameter(const char *s)
}
-#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
+#if !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
static BOOL setupListeningSocketsFromIniFile(const char *s)
{
if (!maxsockets) return TRUE;
@@ -740,7 +759,7 @@ static BOOL setupListeningSocketsFromIniFile(const char *s)
IniFileErrorMessage = IniFileErrorBuffer;
return addListeningSocket(s);
}
-#endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
+#endif // !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
static BOOL readIniFile(const uint_fast8_t pass)
@@ -775,7 +794,7 @@ static BOOL readIniFile(const uint_fast8_t pass)
!setEpidFromIniFileLine(&s, appIndex) ||
!setHwIdFromIniFileLine(&s, appIndex);
}
-# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
+# if !defined(NO_SOCKETS) && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
else if (pass == INI_FILE_PASS_2)
{
lineParseError = !setupListeningSocketsFromIniFile(s);
@@ -784,7 +803,7 @@ static BOOL readIniFile(const uint_fast8_t pass)
{
return FALSE;
}
-# endif // NO_SOCKETS
+# endif // !defined(NO_SOCKETS) && && !defined(SIMPLE_SOCKETS) && !defined(USE_MSRPC)
if (lineParseError)
{
@@ -1065,10 +1084,21 @@ static void parseGeneralArguments() {
#ifndef NO_SOCKETS
#ifndef USE_MSRPC
+ #ifdef ENABLE_DEPRECATED_OPTIONS
+ #ifndef SIMPLE_SOCKETS
case '4':
case '6':
+ printerrorf("Warning: Option -%c is deprecated. Use -L instead.\n", o);
+ /* no break */
+ #endif // SIMPLE_SOCKETS
+ #endif // ENABLE_DEPRECATED_OPTIONS
case 'P':
+ if (o == 'P') defaultport = optarg;
+ #ifdef SIMPLE_SOCKETS
+ ignoreIniFileParameter(INI_PARAM_PORT);
+ #else // !SIMPLE_SOCKETS
ignoreIniFileParameter(INI_PARAM_LISTEN);
+ #endif // !SIMPLE_SOCKETS
break;
#else // USE_MSRPC
case 'P':
@@ -1129,19 +1159,44 @@ static void parseGeneralArguments() {
#endif // NO_LOG
#ifndef NO_SOCKETS
- #ifndef USE_MSRPC
+ #if !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
case 'L':
maxsockets++;
ignoreIniFileParameter(INI_PARAM_LISTEN);
break;
- #endif // USE_MSRPC
+ #if HAVE_FREEBIND
+ case 'F':
+ if (!getArgumentBool(&freebind, optarg)) usage();
+ ignoreIniFileParameter(INI_PARAM_FREEBIND);
+ break;
+ #endif // HAVE_FREEBIND
+ #endif // !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
+ #if defined(ENABLE_DEPRECATED_OPTIONS)
case 'f':
+ #if !defined(_WIN32) || !defined(NO_LOG)
+ printerrorf
+ (
+ "Warning: Option -f is deprecated. Use -"
+ #ifdef _WIN32
+ "e"
+ #else // !_WIN32
+ "de"
+ #endif // !_WIN32
+ " instead.\n"
+ );
+ #ifndef _WIN32
nodaemon = 1;
+ #endif // _WIN32
#ifndef NO_LOG
logstdout = 1;
#endif
+ #if defined(_PEDANTIC) && defined(_WIN32) && defined(NO_LOG)
+ printerrorf("Warning: Option -f has no effect in a Windows version of vlmcsd that has been compiled with logging disabled.\n");
+ #endif // defined(_PEDANTIC) && defined(_WIN32) && defined(NO_LOG)
+ #endif // !defined(_WIN32) || !defined(NO_LOG)
break;
+ #endif // ENABLE_DEPRECATED_OPTIONS
#ifdef _NTSERVICE
case 'U':
@@ -1165,7 +1220,13 @@ static void parseGeneralArguments() {
#endif // _NTSERVICE
case 'D':
+ #ifndef _WIN32
nodaemon = 1;
+ #else // _WIN32
+ #ifdef _PEDANTIC
+ printerrorf("Warning: Option -D has no effect in the Windows version of vlmcsd.\n");
+ #endif // _PEDANTIC
+ #endif // _WIN32
break;
#ifndef NO_LOG
@@ -1175,10 +1236,10 @@ static void parseGeneralArguments() {
#endif // NO_LOG
#endif // NO_SOCKETS
- #ifndef _WIN32
+ #if !defined(_WIN32) && defined(ENABLE_DEPRECATED_OPTIONS)
case 'I': // Backward compatibility with svn681 and earlier
break;
- #endif // _WIN32
+ #endif // !defined(_WIN32) && defined(ENABLE_DEPRECATED_OPTIONS)
#ifndef NO_RANDOM_EPID
case 'r':
@@ -1210,8 +1271,8 @@ static void parseGeneralArguments() {
#endif // NO_SIGHUP
if (GetGid())
{
- printerrorf("Fatal: setgid for %s failed.\n", optarg);
- exit(!0);
+ printerrorf("Fatal: %s for %s failed: %s\n", "setgid", gname, strerror(errno));
+ exit(errno);
}
break;
@@ -1223,8 +1284,8 @@ static void parseGeneralArguments() {
#endif // NO_SIGHUP
if (GetUid())
{
- printerrorf("Fatal: setuid for %s failed.\n", optarg);
- exit(!0);
+ printerrorf("Fatal: %s for %s failed: %s\n", "setuid", uname, strerror(errno));
+ exit(errno);
}
break;
#endif // NO_USER_SWITCH && !_WIN32
@@ -1259,12 +1320,21 @@ static void parseGeneralArguments() {
break;
#endif // !USE_MSRPC
+ #ifndef NO_VERSION_INFORMATION
case 'V':
#ifdef _NTSERVICE
if (IsNTService) break;
#endif
- printf("vlmcsd %s\n", Version);
+ #if defined(__s390__) && !defined(__zarch__) && !defined(__s390x__)
+ printf("vlmcsd %s %i-bit\n", Version, sizeof(void*) == 4 ? 31 : (int)sizeof(void*) << 3);
+ #else
+ printf("vlmcsd %s %i-bit\n", Version, (int)sizeof(void*) << 3);
+ #endif // defined(__s390__) && !defined(__zarch__) && !defined(__s390x__)
+ printPlatform();
+ printCommonFlags();
+ printServerFlags();
exit(0);
+ #endif // NO_VERSION_INFORMATION
default:
usage();
@@ -1429,7 +1499,7 @@ static void allocateSemaphore(void)
#endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
-#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
+#if !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
int setupListeningSockets()
{
int o;
@@ -1437,14 +1507,16 @@ int setupListeningSockets()
SocketList = (SOCKET*)vlmcsd_malloc((size_t)allocsockets * sizeof(SOCKET));
- haveIPv4Stack = checkProtocolStack(AF_INET);
- haveIPv6Stack = checkProtocolStack(AF_INET6);
+ int_fast8_t haveIPv4Stack = checkProtocolStack(AF_INET);
+ int_fast8_t haveIPv6Stack = checkProtocolStack(AF_INET6);
// Reset getopt since we've alread used it
optReset();
for (opterr = 0; ( o = getopt(global_argc, (char* const*)global_argv, optstring) ) > 0; ) switch (o)
{
+# ifdef ENABLE_DEPRECATED_OPTIONS
+
case '4':
if (!haveIPv4Stack)
@@ -1465,18 +1537,19 @@ int setupListeningSockets()
v6required = 1;
break;
- case 'L':
-
- addListeningSocket(optarg);
- break;
+# endif // ENABLE_DEPRECATED_OPTIONS
case 'P':
defaultport = optarg;
break;
- default:
+ case 'L':
+ addListeningSocket(optarg);
+ break;
+
+ default:
break;
}
@@ -1498,8 +1571,13 @@ int setupListeningSockets()
// maxsocket results from first pass parsing the arguments
if (!maxsockets)
{
+# ifdef ENABLE_DEPRECATED_OPTIONS
if (haveIPv6Stack && (v6required || !v4required)) addListeningSocket("::");
if (haveIPv4Stack && (v4required || !v6required)) addListeningSocket("0.0.0.0");
+# else // !ENABLE_DEPRECATED_OPTIONS
+ if (haveIPv6Stack) addListeningSocket("::");
+ if (haveIPv4Stack) addListeningSocket("0.0.0.0");
+# endif // !ENABLE_DEPRECATED_OPTIONS
}
if (!numsockets)
@@ -1510,7 +1588,7 @@ int setupListeningSockets()
return 0;
}
-#endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
+#endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC) && !defined(SIMPLE_SOCKETS)
int server_main(int argc, CARGV argv)
@@ -1566,7 +1644,7 @@ int newmain()
#endif // USE_MSRPC
// Windows can never daemonize
- nodaemon = 1;
+ //nodaemon = 1;
#else // __CYGWIN__
@@ -1585,7 +1663,9 @@ int newmain()
{
InetdMode = 1;
nodaemon = 1;
+ #ifndef SIMPLE_SOCKETS
maxsockets = 0;
+ #endif // SIMPLE_SOCKETS
#ifndef NO_LOG
logstdout = 0;
#endif // NO_LOG
@@ -1614,9 +1694,13 @@ int newmain()
#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
if (!InetdMode)
{
+ #ifdef SIMPLE_SOCKETS
+ if ((error = listenOnAllAddresses())) return error;
+ #else // !SIMPLE_SOCKETS
if ((error = setupListeningSockets())) return error;
+ #endif // !SIMPLE_SOCKETS
}
- #endif // NO_SOCKETS
+ #endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
// After sockets have been set up, we may switch to a lower privileged user
#if !defined(_WIN32) && !defined(NO_USER_SWITCH)
@@ -1625,16 +1709,25 @@ int newmain()
if (!IsRestarted)
{
#endif // NO_SIGHUP
- if (gid != INVALID_GID && setgid(gid))
+ if (gid != INVALID_GID)
{
- printerrorf("Fatal: setgid for %s failed.\n", gname);
- return !0;
+ if (setgid(gid))
+ {
+ printerrorf("Fatal: %s for %s failed: %s\n", "setgid", gname, strerror(errno));
+ return errno;
+ }
+
+ if (setgroups(1, &gid))
+ {
+ printerrorf("Fatal: %s for %s failed: %s\n", "setgroups", gname, strerror(errno));
+ return errno;
+ }
}
if (uid != INVALID_UID && setuid(uid))
{
- printerrorf("Fatal: setuid for %s failed.\n", uname);
- return !0;
+ printerrorf("Fatal: %s for %s failed: %s\n", "setuid", uname, strerror(errno));
+ return errno;
}
#ifndef NO_SIGHUP
}
diff --git a/vlmcsd.h b/vlmcsd.h
index 7845a53..e9d5928 100644
--- a/vlmcsd.h
+++ b/vlmcsd.h
@@ -47,6 +47,7 @@ int server_main(int argc, CARGV argv);
#define INI_PARAM_PORT 14
#define INI_PARAM_RPC_NDR64 15
#define INI_PARAM_RPC_BTFN 16
+#define INI_PARAM_FREEBIND 17
#define INI_FILE_PASS_1 1
#define INI_FILE_PASS_2 2
diff --git a/vlmcsd.ini b/vlmcsd.ini
index 7bd2b98..b5bf237 100644
--- a/vlmcsd.ini
+++ b/vlmcsd.ini
@@ -22,19 +22,23 @@
# Use custom TCP port
# Command line: -P
-# ***The Port directive only works if vlmcsd was compiled to use MS RPC
+# ***The Port directive only works if vlmcsd was compiled to use MS RPC or simple sockets
# ***Use Listen otherwise
-;Port = 1688
+;Port = 1234
# Listen on all IPv4 addresses (default port 1688)
-# Command line: -L (and compatibility options -4, -6, -P)
-# Does not work with MS RPC, use Port=
+# Command line: -L
+# Does not work with MS RPC or simple sockets, use Port=
;Listen = 0.0.0.0:1688
# Listen on all IPv6 addresses (default port 1688)
-# Command line: -L (and compatibility options -4, -6, -P)
+# Command line: -L
;Listen = [::]:1688
+# Allow binding to foreign IP addresses
+# Command line: -F0 and -F1
+;FreeBind = true
+
# Randomize ePIDs at program start up (only those that are not explicitly specified)
# Command line: -r
;RandomizationLevel = 1
@@ -84,9 +88,9 @@
;group = vlmcsdgroup
# Disable or enable the NDR64 transfer syntax in RPC (default enabled)
-# Command line: -n
+# Command line: -N0 and -B1
;UseNDR64 = true
# Disable or enable bind time feature negotiation in RPC (default enabled)
-# Command line: -b
+# Command line: -B0 and -B1
;UseBTFN = true
diff --git a/vlmcsd.ini.5 b/vlmcsd.ini.5
index 0b4edcc..a10813a 100644
--- a/vlmcsd.ini.5
+++ b/vlmcsd.ini.5
@@ -1,4 +1,4 @@
-.TH VLMCSD.INI 5 "September 2015" "Hotbird64" "KMS Activation Manual"
+.TH VLMCSD.INI 5 "June 2016" "Hotbird64" "KMS Activation Manual"
.LO 8
.SH NAME
@@ -34,10 +34,10 @@ Lines, that start with '#' or ';' are treated as comments. Empty lines are ignor
Some \fIargument\fRs are binary arguments that need to be either TRUE or FALSE. You can use "Yes", "On" or "1" as an alias for TRUE and "No", "Off" or "0" as an alias for FALSE. Binary arguments are case-insensitive.
.SH KEYWORDS
-The following \fIkeyword\fRs are defined:
+The following \fIkeyword\fRs are defined (not all keywords may be available depending on the operating system and the options used when \fBvlmcsd\fR(8) was compiled):
.IP "\fBListen\fR"
-This defines on what combinations of IP addresses and ports vlmcsd should listen. \fBListen\fR can be specified more than once. The \fIargument\fR has the form \fIipaddress\fR[:\fIport\fR]. If you omit the \fIport\fR, the default port of 1688 is used. If the \fIipaddress\fR contains colons and a \fIport\fR is used, you must enclose the \fIipaddress\fR in brackets. The default is to listen to 0.0.0.0:1688 and [::]:1688 which means listen to all IPv4 and all IPv6 addresses. See the \fB-L\fR option in \fBvlmcsd\fR(8) for more info about the syntax. If you use \fB-L\fR, \fB-P\fR, \fB-4\fR or \fB-6\fR on the command line, all \fBListen\fR keywords in the ini file will be ignored. The \fBListen\fR keyword cannot be used on Windows and Cygwin if vlmcsd has been compiled to use Microsoft RPC.
+This defines on what combinations of IP addresses and ports vlmcsd should listen. \fBListen\fR can be specified more than once. The \fIargument\fR has the form \fIipaddress\fR[:\fIport\fR]. If you omit the \fIport\fR, the default port of 1688 is used. If the \fIipaddress\fR contains colons and a \fIport\fR is used, you must enclose the \fIipaddress\fR in brackets. The default is to listen to 0.0.0.0:1688 and [::]:1688 which means listen to all IPv4 and all IPv6 addresses. See the \fB-L\fR option in \fBvlmcsd\fR(8) for more info about the syntax. If you use \fB-L\fR or \fB-P\fR on the command line, all \fBListen\fR keywords in the ini file will be ignored. The \fBListen\fR keyword cannot be used if vlmcsd has been compiled to use Microsoft RPC (Windows and Cygwin only) or simple sockets.
Examples:
@@ -48,7 +48,10 @@ Listen = 0.0.0.0:1234
Listen = [fe80::1721:12ff:fe81:d36b%eth0]:1688
.IP "\fBPort\fR"
-Can only be used on Windows and Cygwin if vlmcsd has been compiled to use Microsoft RPC. Causes vlmcsd to listen on that port instead of 1688. On all non-Windows operating systems or if vlmcsd has been compiled to use its own RPC implementation, you must use \fBListen\fR instead.
+Can only be used if vlmcsd has been compiled to use simple sockets or on Windows and Cygwin if \fBvlmcsd\fR(8) has been compiled to use Microsoft RPC. Otherwise you must use \fBListen\fR instead. Causes vlmcsd to listen on that port instead of 1688.
+
+.IP "\fBFreeBind\fR"
+Can be TRUE or FALSE. If TRUE, you can use the \fBListen\fR keyword with IP addresses that are currently not defined on your system. \fBvlmcsd\fR(8) will start listening on these IP addresses as soon as they become available. This keyword is only available under Linux and FreeBSD because no other OS currently supports that feature. FreeBSD supports this only for IPv4 and requires the PRIV_NETINET_BINDANY privilege which is normally assigned to proccesses of the root user.
.IP "\fBUseNDR64\fR"
Can be TRUE or FALSE. Specifies whether you want to use the NDR64 transfer syntax. See options \fB-n0\fR and \fB-n1\fR in \fBvlmcsd\fR(8). The default is TRUE.
diff --git a/vlmcsd.ini.5.dos.txt b/vlmcsd.ini.5.dos.txt
index e31dc3d..c28c3fd 100644
--- a/vlmcsd.ini.5.dos.txt
+++ b/vlmcsd.ini.5.dos.txt
@@ -66,7 +66,9 @@ SYNTAX
KEYWORDS
- The following keywords are defined:
+ The following keywords are defined (not all keywords may be available
+ depending on the operating system and the options used when vlmcsd(8)
+ was compiled):
Listen This defines on what combinations of IP addresses and ports vlm‐
@@ -77,10 +79,10 @@ KEYWORDS
brackets. The default is to listen to 0.0.0.0:1688 and [::]:1688
which means listen to all IPv4 and all IPv6 addresses. See the
-L option in vlmcsd(8) for more info about the syntax. If you
- use -L, -P, -4 or -6 on the command line, all Listen keywords in
- the ini file will be ignored. The Listen keyword cannot be used
- on Windows and Cygwin if vlmcsd has been compiled to use Micro‐
- soft RPC.
+ use -L or -P on the command line, all Listen keywords in the ini
+ file will be ignored. The Listen keyword cannot be used if vlm‐
+ csd has been compiled to use Microsoft RPC (Windows and Cygwin
+ only) or simple sockets.
Examples:
@@ -89,11 +91,21 @@ KEYWORDS
Listen = [fe80::1721:12ff:fe81:d36b%eth0]:1688
- Port Can only be used on Windows and Cygwin if vlmcsd has been com‐
- piled to use Microsoft RPC. Causes vlmcsd to listen on that port
- instead of 1688. On all non-Windows operating systems or if vlm‐
- csd has been compiled to use its own RPC implementation, you
- must use Listen instead.
+ Port Can only be used if vlmcsd has been compiled to use simple sock‐
+ ets or on Windows and Cygwin if vlmcsd(8) has been compiled to
+ use Microsoft RPC. Otherwise you must use Listen instead. Causes
+ vlmcsd to listen on that port instead of 1688.
+
+
+ FreeBind
+ Can be TRUE or FALSE. If TRUE, you can use the Listen keyword
+ with IP addresses that are currently not defined on your system.
+ vlmcsd(8) will start listening on these IP addresses as soon as
+ they become available. This keyword is only available under
+ Linux and FreeBSD because no other OS currently supports that
+ feature. FreeBSD supports this only for IPv4 and requires the
+ PRIV_NETINET_BINDANY privilege which is normally assigned to
+ proccesses of the root user.
UseNDR64
@@ -265,4 +277,4 @@ SEE ALSO
-Hotbird64 September 2015 VLMCSD.INI(5)
+Hotbird64 June 2016 VLMCSD.INI(5)
diff --git a/vlmcsd.ini.5.html b/vlmcsd.ini.5.html
index 84f1860..38f7395 100644
--- a/vlmcsd.ini.5.html
+++ b/vlmcsd.ini.5.html
@@ -1,5 +1,5 @@
-
+
@@ -137,7 +137,9 @@ Binary arguments are case-insensitive.
The following
-keywords are defined:
+keywords are defined (not all keywords may be
+available depending on the operating system and the options
+used when vlmcsd(8) was compiled):
@@ -161,11 +163,11 @@ the ipaddress in brackets. The default is to listen
to 0.0.0.0:1688 and [::]:1688 which means listen to all IPv4
and all IPv6 addresses. See the -L option in
vlmcsd(8) for more info about the syntax. If you use
--L, -P, -4 or -6 on the command
-line, all Listen keywords in the ini file will be
-ignored. The Listen keyword cannot be used on Windows
-and Cygwin if vlmcsd has been compiled to use Microsoft
-RPC.
+-L or -P on the command line, all
+Listen keywords in the ini file will be ignored. The
+Listen keyword cannot be used if vlmcsd has been
+compiled to use Microsoft RPC (Windows and Cygwin only) or
+simple sockets.
Examples:
@@ -187,14 +189,25 @@ Listen = [fe80::1721:12ff:fe81:d36b%eth0]:1688
- Can only be used on Windows and
-Cygwin if vlmcsd has been compiled to use Microsoft RPC.
-Causes vlmcsd to listen on that port instead of 1688. On all
-non-Windows operating systems or if vlmcsd has been compiled
-to use its own RPC implementation, you must use
-Listen instead. | |
+Can only be used if vlmcsd has
+been compiled to use simple sockets or on Windows and Cygwin
+if vlmcsd(8) has been compiled to use Microsoft RPC.
+Otherwise you must use Listen instead. Causes vlmcsd
+to listen on that port instead of 1688.
+FreeBind
+
+Can be TRUE or FALSE. If TRUE,
+you can use the Listen keyword with IP addresses that
+are currently not defined on your system. vlmcsd(8)
+will start listening on these IP addresses as soon as they
+become available. This keyword is only available under Linux
+and FreeBSD because no other OS currently supports that
+feature. FreeBSD supports this only for IPv4 and requires
+the PRIV_NETINET_BINDANY privilege which is normally
+assigned to proccesses of the root user.
+
UseNDR64
Can be TRUE or FALSE. Specifies
diff --git a/vlmcsd.ini.5.pdf b/vlmcsd.ini.5.pdf
index af28f97..ea9a905 100644
Binary files a/vlmcsd.ini.5.pdf and b/vlmcsd.ini.5.pdf differ
diff --git a/vlmcsd.ini.5.unix.txt b/vlmcsd.ini.5.unix.txt
index a0492a4..387f463 100644
--- a/vlmcsd.ini.5.unix.txt
+++ b/vlmcsd.ini.5.unix.txt
@@ -66,7 +66,9 @@ SYNTAX
KEYWORDS
- The following keywords are defined:
+ The following keywords are defined (not all keywords may be available
+ depending on the operating system and the options used when vlmcsd(8)
+ was compiled):
Listen This defines on what combinations of IP addresses and ports vlm‐
@@ -77,10 +79,10 @@ KEYWORDS
brackets. The default is to listen to 0.0.0.0:1688 and [::]:1688
which means listen to all IPv4 and all IPv6 addresses. See the
-L option in vlmcsd(8) for more info about the syntax. If you
- use -L, -P, -4 or -6 on the command line, all Listen keywords in
- the ini file will be ignored. The Listen keyword cannot be used
- on Windows and Cygwin if vlmcsd has been compiled to use Micro‐
- soft RPC.
+ use -L or -P on the command line, all Listen keywords in the ini
+ file will be ignored. The Listen keyword cannot be used if vlm‐
+ csd has been compiled to use Microsoft RPC (Windows and Cygwin
+ only) or simple sockets.
Examples:
@@ -89,11 +91,21 @@ KEYWORDS
Listen = [fe80::1721:12ff:fe81:d36b%eth0]:1688
- Port Can only be used on Windows and Cygwin if vlmcsd has been com‐
- piled to use Microsoft RPC. Causes vlmcsd to listen on that port
- instead of 1688. On all non-Windows operating systems or if vlm‐
- csd has been compiled to use its own RPC implementation, you
- must use Listen instead.
+ Port Can only be used if vlmcsd has been compiled to use simple sock‐
+ ets or on Windows and Cygwin if vlmcsd(8) has been compiled to
+ use Microsoft RPC. Otherwise you must use Listen instead. Causes
+ vlmcsd to listen on that port instead of 1688.
+
+
+ FreeBind
+ Can be TRUE or FALSE. If TRUE, you can use the Listen keyword
+ with IP addresses that are currently not defined on your system.
+ vlmcsd(8) will start listening on these IP addresses as soon as
+ they become available. This keyword is only available under
+ Linux and FreeBSD because no other OS currently supports that
+ feature. FreeBSD supports this only for IPv4 and requires the
+ PRIV_NETINET_BINDANY privilege which is normally assigned to
+ proccesses of the root user.
UseNDR64
@@ -265,4 +277,4 @@ SEE ALSO
-Hotbird64 September 2015 VLMCSD.INI(5)
+Hotbird64 June 2016 VLMCSD.INI(5)
diff --git a/vlmcsd_all.c b/vlmcsd_all.c
deleted file mode 100644
index 6c71a5e..0000000
--- a/vlmcsd_all.c
+++ /dev/null
@@ -1,6009 +0,0 @@
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#if defined(USE_MSRPC) && !defined(_WIN32) && !defined(__CYGWIN__)
-#error Microsoft RPC is only available on Windows and Cygwin
-#endif
-
-#if defined(NO_SOCKETS) && defined(USE_MSRPC)
-#error Cannot use inetd mode with Microsoft RPC
-#endif
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include
-#include
-#include
-#include
-#include
-
-#ifndef _WIN32
-#include
-#include
-#include
-
-#if !defined(NO_LIMIT) && !__minix__
-#include
-#if !__ANDROID__
-#include
-#else // __ANDROID__
-#include
-#endif // __ANDROID__
-#endif // !defined(NO_LIMIT) && !__minix__
-
-#include
-#include
-#include
-#include
-#include
-#endif // !_WIN32
-
-#if __APPLE__
-#include
-#endif // __APPLE__
-
-#if __linux__ && defined(USE_AUXV)
-#include
-#endif
-
-#if __FreeBSD__
-#include
-#endif
-
-#include "vlmcsd.h"
-#include "endian.h"
-#include "shared_globals.h"
-#include "output.h"
-#ifndef USE_MSRPC
-#include "network.h"
-#else // USE_MSRPC
-#include "msrpc-server.h"
-#endif // USE_MSRPC
-#include "ntservice.h"
-#include "helpers.h"
-
-
-static const char* const optstring = "N:B:m:t:w:0:3:H:A:R:u:g:L:p:i:P:l:r:U:W:C:SsfeDd46VvIdqkZ";
-
-#if !defined(NO_SOCKETS)
-#if !defined(USE_MSRPC)
-static uint_fast8_t maxsockets = 0;
-static int_fast8_t haveIPv6Stack = 0;
-static int_fast8_t haveIPv4Stack = 0;
-static int_fast8_t v6required = 0;
-static int_fast8_t v4required = 0;
-#endif // !defined(USE_MSRPC)
-#endif // !defined(NO_SOCKETS)
-
-#ifdef _NTSERVICE
-static int_fast8_t installService = 0;
-static const char *restrict ServiceUser = NULL;
-static const char *restrict ServicePassword = "";
-#endif
-
-#ifndef NO_PID_FILE
-static const char *fn_pid = NULL;
-#endif
-
-#ifndef NO_INI_FILE
-
-#ifdef INI_FILE
-static const char *fn_ini = INI_FILE;
-#else // !INI_FILE
-static const char *fn_ini = NULL;
-#endif // !INI_FILE
-
-static const char* IniFileErrorMessage = "";
-char* IniFileErrorBuffer = NULL;
-#define INIFILE_ERROR_BUFFERSIZE 256
-
-static IniFileParameter_t IniFileParameterList[] =
-{
-# ifndef NO_RANDOM_EPID
- { "RandomizationLevel", INI_PARAM_RANDOMIZATION_LEVEL },
- { "LCID", INI_PARAM_LCID },
-# endif // NO_RANDOM_EPID
-# ifdef USE_MSRPC
- { "Port", INI_PARAM_PORT },
-# endif // USE_MSRPC
-# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- { "Listen", INI_PARAM_LISTEN },
-# if !defined(NO_LIMIT) && !__minix__
- { "MaxWorkers", INI_PARAM_MAX_WORKERS },
-# endif // !defined(NO_LIMIT) && !__minix__
-# endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-# if !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC) & !defined(USE_MSRPC)
- { "ConnectionTimeout", INI_PARAM_CONNECTION_TIMEOUT },
-# endif // !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC) & !defined(USE_MSRPC)
-# ifndef USE_MSRPC
- { "DisconnectClientsImmediately", INI_PARAM_DISCONNECT_IMMEDIATELY },
- { "UseNDR64", INI_PARAM_RPC_NDR64 },
- { "UseBTFN", INI_PARAM_RPC_BTFN },
-# endif // USE_MSRPC
-# ifndef NO_PID_FILE
- { "PIDFile", INI_PARAM_PID_FILE },
-# endif // NO_PID_FILE
-# ifndef NO_LOG
- { "LogFile", INI_PARAM_LOG_FILE },
-# ifndef NO_VERBOSE_LOG
- { "LogVerbose", INI_PARAM_LOG_VERBOSE },
-# endif // NO_VERBOSE_LOG
-# endif // NO_LOG
-# ifndef NO_CUSTOM_INTERVALS
- {"ActivationInterval", INI_PARAM_ACTIVATION_INTERVAL },
- {"RenewalInterval", INI_PARAM_RENEWAL_INTERVAL },
-# endif // NO_CUSTOM_INTERVALS
-# if !defined(NO_USER_SWITCH) && !defined(_WIN32)
- { "user", INI_PARAM_UID },
- { "group", INI_PARAM_GID},
-# endif // !defined(NO_USER_SWITCH) && !defined(_WIN32)
-};
-
-#endif // NO_INI_FILE
-
-
-#if !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-
-#if !defined(USE_THREADS) && !defined(CYGWIN) && !defined(USE_MSRPC)
-static int shmid = -1;
-#endif
-
-#if __ANDROID__ && !defined(USE_THREADS) // Bionic does not wrap these syscalls (willingly because Google fears, developers don't know how to use it)
-
-#ifdef __NR_shmget
-static int shmget(key_t key, size_t size, int shmflg)
-{
- return syscall(__NR_shmget, key, size, shmflg);
-}
-#endif // __NR_shmget
-
-#ifdef __NR_shmat
-static void *shmat(int shmid, const void *shmaddr, int shmflg)
-{
- return (void *)syscall(__NR_shmat, shmid, shmaddr, shmflg);
-}
-#endif // __NR_shmat
-
-#ifdef __NR_shmdt
-static int shmdt(const void *shmaddr)
-{
- return syscall(__NR_shmdt, shmaddr);
-}
-#endif // __NR_shmdt
-
-#ifdef __NR_shmctl
-static int shmctl(int shmid, int cmd, /*struct shmid_ds*/void *buf)
-{
- return syscall(__NR_shmctl, shmid, cmd, buf);
-}
-#endif // __NR_shmctl
-
-#endif // __ANDROID__ && !defined(USE_THREADS)
-
-#endif // !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-
-#ifndef NO_USER_SWITCH
-#ifndef _WIN32
-
-static const char *uname = NULL, *gname = NULL;
-static gid_t gid = INVALID_GID;
-static uid_t uid = INVALID_UID;
-
-// Get Numeric id of user/group
-static char GetNumericId(gid_t *restrict id, const char *const c)
-{
- char* endptr;
- gid_t temp;
-
- temp = (gid_t)strtoll(c, &endptr, 10);
-
- if (!*endptr) *id = temp;
-
- return *endptr;
-}
-
-
-// Get group id from option argument
-static char GetGid()
-{
- struct group *g;
-
- if ((g = getgrnam(optarg)))
- gid = g->gr_gid;
- else
- return GetNumericId(&gid, optarg);
-
- return 0;
-}
-
-
-// Get user id from option argument
-static char GetUid()
-{
- struct passwd *u;
-
- ////PORTABILITY: Assumes uid_t and gid_t are of same size (shouldn't be a problem)
- if ((u = getpwnam(optarg)))
- uid = u->pw_uid;
- else
- return GetNumericId((gid_t*)&uid, optarg);
-
- return 0;
-}
-#endif // _WIN32
-#endif //NO_USER_SWITCH
-
-#ifdef NO_HELP
-static __noreturn void usage()
-{
- printerrorf("Incorrect parameters\n\n");
- exit(!0);
-}
-#else // HELP
-
-
-static __noreturn void usage()
-{
- printerrorf("vlmcsd %s\n"
- "\nUsage:\n"
- " %s [ options ]\n\n"
- "Where:\n"
- #ifndef NO_CL_PIDS
- " -w always use for Windows\n"
- " -0 always use for Office2010\n"
- " -3 always use for Office2013\n"
- " -H always use hardware Id \n"
- #endif // NO_CL_PIDS
- #if !defined(_WIN32) && !defined(NO_USER_SWITCH)
- " -u set uid to \n"
- " -g set gid to \n"
- #endif // !defined(_WIN32) && !defined(NO_USER_SWITCH)
- #ifndef NO_RANDOM_EPID
- " -r 0|1|2\t\tset ePID randomization level (default 1)\n"
- " -C \t\tuse fixed in random ePIDs\n"
- #endif // NO_RANDOM_EPID
- #ifndef NO_SOCKETS
- #ifndef USE_MSRPC
- " -4\t\t\tuse IPv4\n"
- " -6\t\t\tuse IPv6\n"
- " -L [:]\tlisten on IP address with optional \n"
- " -P \t\tset TCP port for subsequent -L statements (default 1688)\n"
- #else // USE_MSRPC
- " -P \t\tuse TCP port (default 1688)\n"
- #endif // USE_MSRPC
- #if !defined(NO_LIMIT) && !__minix__
- " -m \t\tHandle max. simultaneously (default no limit)\n"
- #endif // !defined(NO_LIMIT) && !__minix__
- #ifdef _NTSERVICE
- " -s install vlmcsd as an NT service. Ignores -e"
- #ifndef _WIN32
- ", -f and -D"
- #endif // _WIN32
- "\n"
- " -S remove vlmcsd service. Ignores all other options\n"
- " -U run NT service as . Must be used with -s\n"
- " -W optional for -U. Must be used with -s\n"
- #endif // _NTSERVICE
- #ifndef NO_LOG
- " -e log to stdout\n"
- #endif // NO_LOG
- #ifndef _WIN32 //
- " -D run in foreground\n"
- " -f run in foreground"
- #ifndef NO_LOG
- " and log to stdout"
- #endif // NO_LOG
- "\n"
- #endif // _WIN32
- #endif // NO_SOCKETS
- #ifndef USE_MSRPC
- #if !defined(NO_TIMEOUT) && !__minix__
- " -t \t\tdisconnect clients after of inactivity (default 30)\n"
- #endif // !defined(NO_TIMEOUT) && !__minix__
- " -d\t\t\tdisconnect clients after each request\n"
- " -k\t\t\tdon't disconnect clients after each request (default)\n"
- " -N0, -N1\t\tdisable/enable NDR64\n"
- " -B0, -B1\t\tdisable/enable bind time feature negotiation\n"
- #endif // USE_MSRPC
- #ifndef NO_PID_FILE
- " -p write pid to \n"
- #endif // NO_PID_FILE
- #ifndef NO_INI_FILE
- " -i \t\tuse config file \n"
- #endif // NO_INI_FILE
- #ifndef NO_CUSTOM_INTERVALS
- " -R renew activation every (default 1w)\n"
- " -A retry activation every (default 2h)\n"
- #endif // NO_CUSTOM_INTERVALS
- #ifndef NO_LOG
- #ifndef _WIN32
- " -l syslog log to syslog\n"
- #endif // _WIN32
- " -l log to \n"
- #ifndef NO_VERBOSE_LOG
- " -v\t\t\tlog verbose\n"
- " -q\t\t\tdon't log verbose (default)\n"
- #endif // NO_VERBOSE_LOG
- #endif // NO_LOG
- " -V display version information and exit"
- "\n",
- Version, global_argv[0]);
-
- exit(!0);
-}
-#endif // HELP
-
-
-#ifndef NO_CUSTOM_INTERVALS
-
-// Convert time span strings (e.g. "2h", "5w") to minutes
-__pure static DWORD timeSpanString2Minutes(const char *const restrict argument)
-{
- char *unitId;
-
- long long val = strtoll(argument, &unitId, 10);
-
- switch(toupper((int)*unitId))
- {
- case 0:
- case 'M':
- break;
- case 'H':
- val *= 60;
- break;
- case 'D':
- val *= 60 * 24;
- break;
- case 'W':
- val *= 60 * 24 * 7;
- break;
- case 'S':
- val /= 60;
- break;
- default:
- return 0;
- }
-
- if (val < 1) val = 1;
- if (val > UINT_MAX) val = UINT_MAX;
-
- return (DWORD)val;
-}
-
-
-#ifndef NO_INI_FILE
-__pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char *const restrict argument)
-{
- DWORD val = timeSpanString2Minutes(argument);
- if (!val)
- {
- IniFileErrorMessage = "Incorrect time span.";
- return FALSE;
- }
-
- *result = val;
- return TRUE;
-}
-#endif // NO_INI_FILE
-
-
-__pure static DWORD getTimeSpanFromCommandLine(const char *const restrict optarg, const char optchar)
-{
- long long val = timeSpanString2Minutes(optarg);
-
- if (!val)
- {
- printerrorf("Fatal: No valid time span specified in option -%c.\n", optchar);
- exit (!0);
- }
-
- return (DWORD)val;
-}
-
-#endif // NO_CUSTOM_INTERVALS
-
-
-#ifndef NO_INI_FILE
-static void ignoreIniFileParameter(uint_fast8_t iniFileParameterId)
-{
- uint_fast8_t i;
-
- for (i = 0; i < _countof(IniFileParameterList); i++)
- {
- if (IniFileParameterList[i].Id != iniFileParameterId) continue;
- IniFileParameterList[i].Id = 0;
- break;
- }
-}
-#else // NO_INI_FILE
-#define ignoreIniFileParameter(x)
-#endif // NO_INI_FILE
-
-
-#ifndef NO_INI_FILE
-static BOOL getIniFileArgumentBool(int_fast8_t *result, const char *const argument)
-{
- IniFileErrorMessage = "Argument must be true/on/yes/1 or false/off/no/0";
- return getArgumentBool(result, argument);
-}
-
-
-static BOOL getIniFileArgumentInt(unsigned int *result, const char *const argument, const unsigned int min, const unsigned int max)
-{
- unsigned int tempResult;
-
- if (!stringToInt(argument, min, max, &tempResult))
- {
- snprintf(IniFileErrorBuffer, INIFILE_ERROR_BUFFERSIZE, "Must be integer between %u and %u", min, max);
- IniFileErrorMessage = IniFileErrorBuffer;
- return FALSE;
- }
-
- *result = tempResult;
- return TRUE;
-}
-
-
-static char* allocateStringArgument(const char *const argument)
-{
- char* result = (char*)vlmcsd_malloc(strlen(argument) + 1);
- strcpy(result, argument);
- return result;
-}
-
-
-static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
-{
- unsigned int result;
- BOOL success = TRUE;
-
- switch(id)
- {
-# if !defined(NO_USER_SWITCH) && !defined(_WIN32)
-
- case INI_PARAM_GID:
- {
- struct group *g;
- IniFileErrorMessage = "Invalid group id or name";
- if (!(gname = allocateStringArgument(iniarg))) return FALSE;
-
- if ((g = getgrnam(iniarg)))
- gid = g->gr_gid;
- else
- success = !GetNumericId(&gid, iniarg);
- break;
- }
-
- case INI_PARAM_UID:
- {
- struct passwd *p;
- IniFileErrorMessage = "Invalid user id or name";
- if (!(uname = allocateStringArgument(iniarg))) return FALSE;
-
- if ((p = getpwnam(iniarg)))
- uid = p->pw_uid;
- else
- success = !GetNumericId(&uid, iniarg);
- break;
- }
-
-# endif // !defined(NO_USER_SWITCH) && !defined(_WIN32)
-
-# ifndef NO_RANDOM_EPID
-
- case INI_PARAM_LCID:
- success = getIniFileArgumentInt(&result, iniarg, 0, 32767);
- if (success) Lcid = (uint16_t)result;
- break;
-
- case INI_PARAM_RANDOMIZATION_LEVEL:
- success = getIniFileArgumentInt(&result, iniarg, 0, 2);
- if (success) RandomizationLevel = (int_fast8_t)result;
- break;
-
-# endif // NO_RANDOM_EPID
-
-# ifdef USE_MSRPC
-
- case INI_PARAM_PORT:
- defaultport = allocateStringArgument(iniarg);
- break;
-
-# endif // USE_MSRPC
-
-# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
- case INI_PARAM_LISTEN:
- maxsockets++;
- return TRUE;
-
-# if !defined(NO_LIMIT) && !__minix__
-
- case INI_PARAM_MAX_WORKERS:
-# ifdef USE_MSRPC
- success = getIniFileArgumentInt(&MaxTasks, iniarg, 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT);
-# else // !USE_MSRPC
- success = getIniFileArgumentInt(&MaxTasks, iniarg, 1, SEM_VALUE_MAX);
-# endif // !USE_MSRPC
- break;
-
-# endif // !defined(NO_LIMIT) && !__minix__
-# endif // NO_SOCKETS
-
-# ifndef NO_PID_FILE
-
- case INI_PARAM_PID_FILE:
- fn_pid = allocateStringArgument(iniarg);
- break;
-
-# endif // NO_PID_FILE
-
-# ifndef NO_LOG
-
- case INI_PARAM_LOG_FILE:
- fn_log = allocateStringArgument(iniarg);
- break;
-
-# ifndef NO_VERBOSE_LOG
- case INI_PARAM_LOG_VERBOSE:
- success = getIniFileArgumentBool(&logverbose, iniarg);
- break;
-
-# endif // NO_VERBOSE_LOG
-# endif // NO_LOG
-
-# ifndef NO_CUSTOM_INTERVALS
-
- case INI_PARAM_ACTIVATION_INTERVAL:
- success = getTimeSpanFromIniFile(&VLActivationInterval, iniarg);
- break;
-
- case INI_PARAM_RENEWAL_INTERVAL:
- success = getTimeSpanFromIniFile(&VLRenewalInterval, iniarg);
- break;
-
-# endif // NO_CUSTOM_INTERVALS
-
-# ifndef USE_MSRPC
-
-# if !defined(NO_TIMEOUT) && !__minix__
-
- case INI_PARAM_CONNECTION_TIMEOUT:
- success = getIniFileArgumentInt(&result, iniarg, 1, 600);
- if (success) ServerTimeout = (DWORD)result;
- break;
-
-# endif // !defined(NO_TIMEOUT) && !__minix__
-
- case INI_PARAM_DISCONNECT_IMMEDIATELY:
- success = getIniFileArgumentBool(&DisconnectImmediately, iniarg);
- break;
-
- case INI_PARAM_RPC_NDR64:
- success = getIniFileArgumentBool(&UseRpcNDR64, iniarg);
- break;
-
- case INI_PARAM_RPC_BTFN:
- success = getIniFileArgumentBool(&UseRpcBTFN, iniarg);
- break;
-
-# endif // USE_MSRPC
-
- default:
- return FALSE;
- }
-
- return success;
-}
-
-
-static __pure int isControlCharOrSlash(const char c)
-{
- if ((unsigned char)c < '!') return !0;
- if (c == '/') return !0;
- return 0;
-}
-
-
-static void iniFileLineNextWord(const char **s)
-{
- while ( **s && isspace((int)**s) ) (*s)++;
-}
-
-
-static BOOL setHwIdFromIniFileLine(const char **s, const ProdListIndex_t index)
-{
- iniFileLineNextWord(s);
-
- if (**s == '/')
- {
- if (KmsResponseParameters[index].HwId) return TRUE;
-
- BYTE* HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6 *)0)->HwId));
- hex2bin(HwId, *s + 1, sizeof(((RESPONSE_V6 *)0)->HwId));
- KmsResponseParameters[index].HwId = HwId;
- }
-
- return TRUE;
-}
-
-
-static BOOL checkGuidInIniFileLine(const char **s, ProdListIndex_t *const index)
-{
- GUID AppGuid;
-
- if (!string2Uuid(*s, &AppGuid)) return FALSE;
-
- (*s) += GUID_STRING_LENGTH;
- getProductNameHE(&AppGuid, AppList, index);
-
- if (*index > getAppListSize() - 2)
- {
- IniFileErrorMessage = "Unknown App Guid.";
- return FALSE;
- }
-
- iniFileLineNextWord(s);
- if ( *(*s)++ != '=' ) return FALSE;
-
- return TRUE;
-}
-
-
-static BOOL setEpidFromIniFileLine(const char **s, const ProdListIndex_t index)
-{
- iniFileLineNextWord(s);
- const char *savedPosition = *s;
- uint_fast16_t i;
-
- for (i = 0; !isControlCharOrSlash(**s); i++)
- {
- if (utf8_to_ucs2_char((const unsigned char*)*s, (const unsigned char**)s) == (WCHAR)~0)
- {
- return FALSE;
- }
- }
-
- if (i < 1 || i >= PID_BUFFER_SIZE) return FALSE;
- if (KmsResponseParameters[index].Epid) return TRUE;
-
- size_t size = *s - savedPosition + 1;
-
- char* epidbuffer = (char*)vlmcsd_malloc(size);
- memcpy(epidbuffer, savedPosition, size - 1);
- epidbuffer[size - 1] = 0;
-
- KmsResponseParameters[index].Epid = epidbuffer;
-
- #ifndef NO_LOG
- KmsResponseParameters[index].EpidSource = fn_ini;
- #endif //NO_LOG
-
- return TRUE;
-}
-
-
-static BOOL getIniFileArgument(const char **s)
-{
- while (!isspace((int)**s) && **s != '=' && **s) (*s)++;
- iniFileLineNextWord(s);
-
- if (*((*s)++) != '=')
- {
- IniFileErrorMessage = "'=' required after keyword.";
- return FALSE;
- }
-
- iniFileLineNextWord(s);
-
- if (!**s)
- {
- IniFileErrorMessage = "missing argument after '='.";
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-static BOOL handleIniFileParameter(const char *s)
-{
- uint_fast8_t i;
-
- for (i = 0; i < _countof(IniFileParameterList); i++)
- {
- if (strncasecmp(IniFileParameterList[i].Name, s, strlen(IniFileParameterList[i].Name))) continue;
- if (!IniFileParameterList[i].Id) return TRUE;
-
- if (!getIniFileArgument(&s)) return FALSE;
-
- return setIniFileParameter(IniFileParameterList[i].Id, s);
- }
-
- IniFileErrorMessage = "Unknown keyword.";
- return FALSE;
-}
-
-
-#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-static BOOL setupListeningSocketsFromIniFile(const char *s)
-{
- if (!maxsockets) return TRUE;
- if (strncasecmp("Listen", s, 6)) return TRUE;
- if (!getIniFileArgument(&s)) return TRUE;
-
- snprintf(IniFileErrorBuffer, INIFILE_ERROR_BUFFERSIZE, "Cannot listen on %s.", s);
- IniFileErrorMessage = IniFileErrorBuffer;
- return addListeningSocket(s);
-}
-#endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
-
-static BOOL readIniFile(const uint_fast8_t pass)
-{
- char line[256];
- const char *s;
- ProdListIndex_t appIndex;
- unsigned int lineNumber;
- uint_fast8_t lineParseError;
-
- FILE *restrict f;
- BOOL result = TRUE;
-
- IniFileErrorBuffer = (char*)vlmcsd_malloc(INIFILE_ERROR_BUFFERSIZE);
-
- if ( !(f = fopen(fn_ini, "r") )) return FALSE;
-
- for (lineNumber = 1; (s = fgets(line, sizeof(line), f)); lineNumber++)
- {
- line[strlen(line) - 1] = 0;
-
- iniFileLineNextWord(&s);
- if (*s == ';' || *s == '#' || !*s) continue;
-
-# ifndef NO_SOCKETS
- if (pass == INI_FILE_PASS_1)
-# endif // NO_SOCKETS
- {
- if (handleIniFileParameter(s)) continue;
-
- lineParseError = !checkGuidInIniFileLine(&s, &appIndex) ||
- !setEpidFromIniFileLine(&s, appIndex) ||
- !setHwIdFromIniFileLine(&s, appIndex);
- }
-# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- else if (pass == INI_FILE_PASS_2)
- {
- lineParseError = !setupListeningSocketsFromIniFile(s);
- }
- else
- {
- return FALSE;
- }
-# endif // NO_SOCKETS
-
- if (lineParseError)
- {
- printerrorf("Warning: %s line %u: \"%s\". %s\n", fn_ini, lineNumber, line, IniFileErrorMessage);
- continue;
- }
- }
-
- if (ferror(f)) result = FALSE;
-
- free(IniFileErrorBuffer);
- fclose(f);
-
-# if !defined(NO_SOCKETS) && !defined(NO_LOG)
-
- if (pass == INI_FILE_PASS_1 && !InetdMode && result)
- {
-# ifdef _NTSERVICE
- if (!installService)
-# endif // _NTSERVICE
- logger("Read ini file %s\n", fn_ini);
- }
-
-# endif // !defined(NO_SOCKETS) && !defined(NO_LOG)
-
- return result;
-}
-#endif // NO_INI_FILE
-
-
-#if !defined(NO_SOCKETS)
-#if !defined(_WIN32)
-#if !defined(NO_SIGHUP)
-static void exec_self(char** argv)
-{
-# if __linux__ && defined(USE_AUXV)
-
- char *execname_ptr = (char*)getauxval(AT_EXECFN);
- if (execname_ptr) execv(execname_ptr, argv);
-
-# elif (__linux__ || __CYGWIN__) && !defined(NO_PROCFS)
-
- execv(realpath("/proc/self/exe", NULL), argv);
-
-# elif (__FreeBSD__) && !defined(NO_PROCFS)
-
- int mib[4];
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PATHNAME;
- mib[3] = -1;
- char path[PATH_MAX + 1];
- size_t cb = sizeof(path);
- if (!sysctl(mib, 4, path, &cb, NULL, 0)) execv(path, argv);
-
-# elif (__DragonFly__) && !defined(NO_PROCFS)
-
- execv(realpath("/proc/curproc/file", NULL), argv);
-
-# elif __NetBSD__ && !defined(NO_PROCFS)
-
- execv(realpath("/proc/curproc/exe", NULL), argv);
-
-# elif __sun__
-
- const char* exename = getexecname();
- if (exename) execv(exename, argv);
-
-# elif __APPLE__
-
- char path[PATH_MAX + 1];
- uint32_t size = sizeof(path);
- if (_NSGetExecutablePath(path, &size) == 0) execv(path, argv);
-
-# else
-
- execvp(argv[0], argv);
-
-# endif
-}
-
-
-static void HangupHandler(const int signal_unused)
-{
- int i;
- int_fast8_t daemonize_protection = TRUE;
- CARGV argv_in = multi_argv == NULL ? global_argv : multi_argv;
- int argc_in = multi_argc == 0 ? global_argc : multi_argc;
- const char** argv_out = (const char**)vlmcsd_malloc((argc_in + 2) * sizeof(char**));
-
- for (i = 0; i < argc_in; i++)
- {
- if (!strcmp(argv_in[i], "-Z")) daemonize_protection = FALSE;
- argv_out[i] = argv_in[i];
- }
-
- argv_out[argc_in] = argv_out[argc_in + 1] = NULL;
- if (daemonize_protection) argv_out[argc_in] = (char*) "-Z";
-
- exec_self((char**)argv_out);
-
-# ifndef NO_LOG
- logger("Fatal: Unable to restart on SIGHUP: %s\n", strerror(errno));
-# endif
-
-# ifndef NO_PID_FILE
- if (fn_pid) unlink(fn_pid);
-# endif // NO_PID_FILE
- exit(errno);
-}
-#endif // NO_SIGHUP
-
-
-static void terminationHandler(const int signal_unused)
-{
- cleanup();
- exit(0);
-}
-
-
-#if defined(CHILD_HANDLER) || __minix__
-static void childHandler(const int signal)
-{
- waitpid(-1, NULL, WNOHANG);
-}
-#endif // defined(CHILD_HANDLER) || __minix__
-
-
-static int daemonizeAndSetSignalAction()
-{
- struct sigaction sa;
- sigemptyset(&sa.sa_mask);
-
-# ifndef NO_LOG
- if ( !nodaemon) if (daemon(!0, logstdout))
-# else // NO_LOG
- if ( !nodaemon) if (daemon(!0, 0))
-# endif // NO_LOG
- {
- printerrorf("Fatal: Could not daemonize to background.\n");
- return(errno);
- }
-
- if (!InetdMode)
- {
-# ifndef USE_THREADS
-
-# if defined(CHILD_HANDLER) || __minix__
- sa.sa_handler = childHandler;
-# else // !(defined(CHILD_HANDLER) || __minix__)
- sa.sa_handler = SIG_IGN;
-# endif // !(defined(CHILD_HANDLER) || __minix__)
- sa.sa_flags = SA_NOCLDWAIT;
-
- if (sigaction(SIGCHLD, &sa, NULL))
- return(errno);
-
-# endif // !USE_THREADS
-
- sa.sa_handler = terminationHandler;
- sa.sa_flags = 0;
-
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
-
-# ifndef NO_SIGHUP
- sa.sa_handler = HangupHandler;
- sa.sa_flags = SA_NODEFER;
- sigaction(SIGHUP, &sa, NULL);
-# endif // NO_SIGHUP
- }
-
- return 0;
-}
-
-
-#else // _WIN32
-
-static BOOL terminationHandler(const DWORD fdwCtrlType)
-{
- // What a lame substitute for Unix signal handling
- switch(fdwCtrlType)
- {
- case CTRL_C_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- cleanup();
- exit(0);
- default:
- return FALSE;
- }
-}
-
-
-static DWORD daemonizeAndSetSignalAction()
-{
- if(!SetConsoleCtrlHandler( (PHANDLER_ROUTINE) terminationHandler, TRUE ))
- {
- #ifndef NO_LOG
- DWORD rc = GetLastError();
- logger("Warning: Could not register Windows signal handler: Error %u\n", rc);
- #endif // NO_LOG
- }
-
- return ERROR_SUCCESS;
-}
-#endif // _WIN32
-#endif // !defined(NO_SOCKETS)
-
-
-// Workaround for Cygwin fork bug (only affects cygwin processes that are Windows services)
-// Best is to compile for Cygwin with threads. fork() is slow and unreliable on Cygwin
-#if !defined(NO_INI_FILE) || !defined(NO_LOG) || !defined(NO_CL_PIDS)
-__pure static char* getCommandLineArg(char *const restrict optarg)
-{
- #if !defined (__CYGWIN__) || defined(USE_THREADS) || defined(NO_SOCKETS)
- return optarg;
- #else
- if (!IsNTService) return optarg;
-
- return allocateStringArgument(optarg);
- #endif
-}
-#endif // !defined(NO_INI_FILE) || !defined(NO_LOG) || !defined(NO_CL_PIDS)
-
-
-static void parseGeneralArguments() {
- int o;
-
- #ifndef NO_CL_PIDS
- BYTE* HwId;
- #endif // NO_CL_PIDS
-
- for (opterr = 0; ( o = getopt(global_argc, (char* const*)global_argv, optstring) ) > 0; ) switch (o)
- {
- #if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
- case 'Z':
- IsRestarted = TRUE;
- nodaemon = TRUE;
- break;
- #endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
-
- #ifndef NO_CL_PIDS
- case 'w':
- KmsResponseParameters[APP_ID_WINDOWS].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[APP_ID_WINDOWS].EpidSource = "command line";
- #endif // NO_LOG
- break;
-
- case '0':
- KmsResponseParameters[APP_ID_OFFICE2010].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[APP_ID_OFFICE2010].EpidSource = "command line";
- #endif // NO_LOG
- break;
-
- case '3':
- KmsResponseParameters[APP_ID_OFFICE2013].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[APP_ID_OFFICE2013].EpidSource = "command line";
- #endif // NO_LOG
- break;
-
- case 'H':
- HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6 *)0)->HwId));
-
- hex2bin(HwId, optarg, sizeof(((RESPONSE_V6 *)0)->HwId));
-
- KmsResponseParameters[APP_ID_WINDOWS].HwId = HwId;
- KmsResponseParameters[APP_ID_OFFICE2010].HwId = HwId;
- KmsResponseParameters[APP_ID_OFFICE2013].HwId = HwId;
- break;
- #endif // NO_CL_PIDS
-
- #ifndef NO_SOCKETS
-
- #ifndef USE_MSRPC
- case '4':
- case '6':
- case 'P':
- ignoreIniFileParameter(INI_PARAM_LISTEN);
- break;
- #else // USE_MSRPC
- case 'P':
- defaultport = optarg;
- ignoreIniFileParameter(INI_PARAM_PORT);
- break;
- #endif // USE_MSRPC
-
- #if !defined(NO_LIMIT) && !__minix__
-
- case 'm':
- #ifdef USE_MSRPC
- MaxTasks = getOptionArgumentInt(o, 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT);
- #else // !USE_MSRPC
- MaxTasks = getOptionArgumentInt(o, 1, SEM_VALUE_MAX);
- #endif // !USE_MSRPC
- ignoreIniFileParameter(INI_PARAM_MAX_WORKERS);
- break;
-
- #endif // !defined(NO_LIMIT) && !__minix__
- #endif // NO_SOCKETS
-
- #if !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC)
- case 't':
- ServerTimeout = getOptionArgumentInt(o, 1, 600);
- ignoreIniFileParameter(INI_PARAM_CONNECTION_TIMEOUT);
- break;
- #endif // !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC)
-
- #ifndef NO_PID_FILE
- case 'p':
- fn_pid = getCommandLineArg(optarg);
- ignoreIniFileParameter(INI_PARAM_PID_FILE);
- break;
- #endif
-
- #ifndef NO_INI_FILE
- case 'i':
- fn_ini = getCommandLineArg(optarg);
- if (!strcmp(fn_ini, "-")) fn_ini = NULL;
- break;
- #endif
-
- #ifndef NO_LOG
- case 'l':
- fn_log = getCommandLineArg(optarg);
- ignoreIniFileParameter(INI_PARAM_LOG_FILE);
- break;
-
- #ifndef NO_VERBOSE_LOG
- case 'v':
- case 'q':
- logverbose = o == 'v';
- ignoreIniFileParameter(INI_PARAM_LOG_VERBOSE);
- break;
-
- #endif // NO_VERBOSE_LOG
- #endif // NO_LOG
-
- #ifndef NO_SOCKETS
- #ifndef USE_MSRPC
- case 'L':
- maxsockets++;
- ignoreIniFileParameter(INI_PARAM_LISTEN);
- break;
- #endif // USE_MSRPC
-
- case 'f':
- nodaemon = 1;
- #ifndef NO_LOG
- logstdout = 1;
- #endif
- break;
-
- #ifdef _NTSERVICE
- case 'U':
- ServiceUser = optarg;
- break;
-
- case 'W':
- ServicePassword = optarg;
- break;
-
- case 's':
- #ifndef USE_MSRPC
- if (InetdMode) usage();
- #endif // USE_MSRPC
- if (!IsNTService) installService = 1; // Install
- break;
-
- case 'S':
- if (!IsNTService) installService = 2; // Remove
- break;
- #endif // _NTSERVICE
-
- case 'D':
- nodaemon = 1;
- break;
-
- #ifndef NO_LOG
- case 'e':
- logstdout = 1;
- break;
- #endif // NO_LOG
- #endif // NO_SOCKETS
-
- #ifndef _WIN32
- case 'I': // Backward compatibility with svn681 and earlier
- break;
- #endif // _WIN32
-
- #ifndef NO_RANDOM_EPID
- case 'r':
- RandomizationLevel = (int_fast8_t)getOptionArgumentInt(o, 0, 2);
- ignoreIniFileParameter(INI_PARAM_RANDOMIZATION_LEVEL);
- break;
-
- case 'C':
- Lcid = (uint16_t)getOptionArgumentInt(o, 0, 32767);
-
- ignoreIniFileParameter(INI_PARAM_LCID);
-
- #ifdef _PEDANTIC
- if (!IsValidLcid(Lcid))
- {
- printerrorf("Warning: %s is not a valid LCID.\n", optarg);
- }
- #endif // _PEDANTIC
-
- break;
- #endif // NO_RANDOM_PID
-
- #if !defined(NO_USER_SWITCH) && !defined(_WIN32)
- case 'g':
- gname = optarg;
- ignoreIniFileParameter(INI_PARAM_GID);
- #ifndef NO_SIGHUP
- if (!IsRestarted)
- #endif // NO_SIGHUP
- if (GetGid())
- {
- printerrorf("Fatal: setgid for %s failed.\n", optarg);
- exit(!0);
- }
- break;
-
- case 'u':
- uname = optarg;
- ignoreIniFileParameter(INI_PARAM_UID);
- #ifndef NO_SIGHUP
- if (!IsRestarted)
- #endif // NO_SIGHUP
- if (GetUid())
- {
- printerrorf("Fatal: setuid for %s failed.\n", optarg);
- exit(!0);
- }
- break;
- #endif // NO_USER_SWITCH && !_WIN32
-
- #ifndef NO_CUSTOM_INTERVALS
- case 'R':
- VLRenewalInterval = getTimeSpanFromCommandLine(optarg, o);
- ignoreIniFileParameter(INI_PARAM_RENEWAL_INTERVAL);
- break;
-
- case 'A':
- VLActivationInterval = getTimeSpanFromCommandLine(optarg, o);
- ignoreIniFileParameter(INI_PARAM_ACTIVATION_INTERVAL);
- break;
- #endif
-
- #ifndef USE_MSRPC
- case 'd':
- case 'k':
- DisconnectImmediately = o == 'd';
- ignoreIniFileParameter(INI_PARAM_DISCONNECT_IMMEDIATELY);
- break;
-
- case 'N':
- if (!getArgumentBool(&UseRpcNDR64, optarg)) usage();
- ignoreIniFileParameter(INI_PARAM_RPC_NDR64);
- break;
-
- case 'B':
- if (!getArgumentBool(&UseRpcBTFN, optarg)) usage();
- ignoreIniFileParameter(INI_PARAM_RPC_BTFN);
- break;
- #endif // !USE_MSRPC
-
- case 'V':
- #ifdef _NTSERVICE
- if (IsNTService) break;
- #endif
- printf("vlmcsd %s\n", Version);
- exit(0);
-
- default:
- usage();
- }
-
- // Do not allow non-option arguments
- if (optind != global_argc)
- usage();
-
- #ifdef _NTSERVICE
- // -U and -W must be used with -s
- if ((ServiceUser || *ServicePassword) && installService != 1) usage();
- #endif // _NTSERVICE
-}
-
-
-#ifndef NO_PID_FILE
-static void writePidFile()
-{
-# ifndef NO_SIGHUP
- if (IsRestarted) return;
-# endif // NO_SIGHUP
-
- if (fn_pid && !InetdMode)
- {
- FILE *_f = fopen(fn_pid, "w");
-
- if ( _f )
- {
- fprintf(_f, "%u", (uint32_t)getpid());
- fclose(_f);
- }
-
- #ifndef NO_LOG
- else
- {
- logger("Warning: Cannot write pid file '%s'. %s.\n", fn_pid, strerror(errno));
- }
- #endif // NO_LOG
- }
-}
-#else
-#define writePidFile(x)
-#endif // NO_PID_FILE
-
-#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
-void cleanup()
-{
-
- if (!InetdMode)
- {
- #ifndef NO_PID_FILE
- if (fn_pid) unlink(fn_pid);
- #endif // NO_PID_FILE
- closeAllListeningSockets();
-
- #if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !defined(_WIN32) && !__minix__
- sem_unlink("/vlmcsd");
- #if !defined(USE_THREADS) && !defined(CYGWIN)
- if (shmid >= 0)
- {
- if (Semaphore != (sem_t*)-1) shmdt(Semaphore);
- shmctl(shmid, IPC_RMID, NULL);
- }
- #endif // !defined(USE_THREADS) && !defined(CYGWIN)
- #endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !defined(_WIN32) && !__minix__
-
- #ifndef NO_LOG
- logger("vlmcsd %s was shutdown\n", Version);
- #endif // NO_LOG
- }
-
-}
-
-#elif defined(USE_MSRPC)
-
-void cleanup()
-{
-# ifndef NO_PID_FILE
- if (fn_pid) unlink(fn_pid);
-# endif // NO_PID_FILE
-
-# ifndef NO_LOG
- logger("vlmcsd %s was shutdown\n", Version);
-# endif // NO_LOG
-}
-
-#else // Neither Sockets nor RPC
-
-__pure void cleanup() {}
-
-#endif // Neither Sockets nor RPC
-
-
-#if !defined(USE_MSRPC) && !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
-// Get a semaphore for limiting the maximum concurrent tasks
-static void allocateSemaphore(void)
-{
- #ifdef USE_THREADS
- #define sharemode 0
- #else
- #define sharemode 1
- #endif
-
- #ifndef _WIN32
- sem_unlink("/vlmcsd");
- #endif
-
- if(MaxTasks < SEM_VALUE_MAX && !InetdMode)
- {
- #ifndef _WIN32
-
- #if !defined(USE_THREADS) && !defined(CYGWIN)
-
- if ((Semaphore = sem_open("/vlmcsd", O_CREAT /*| O_EXCL*/, 0700, MaxTasks)) == SEM_FAILED) // fails on many systems
- {
- // We didn't get a named Semaphore (/dev/shm on Linux) so let's try our own shared page
-
- if (
- ( shmid = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600) ) < 0 ||
- ( Semaphore = (sem_t*)shmat(shmid, NULL, 0) ) == (sem_t*)-1 ||
- sem_init(Semaphore, 1, MaxTasks) < 0
- )
- {
- int errno_save = errno;
- if (Semaphore != (sem_t*)-1) shmdt(Semaphore);
- if (shmid >= 0) shmctl(shmid, IPC_RMID, NULL);
- printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno_save));
- MaxTasks = SEM_VALUE_MAX;
- }
- }
-
- #else // THREADS or CYGWIN
-
- Semaphore = (sem_t*)vlmcsd_malloc(sizeof(sem_t));
-
- if (sem_init(Semaphore, sharemode, MaxTasks) < 0) // sem_init is not implemented on Darwin (returns ENOSYS)
- {
- free(Semaphore);
-
- if ((Semaphore = sem_open("/vlmcsd", O_CREAT /*| O_EXCL*/, 0700, MaxTasks)) == SEM_FAILED)
- {
- printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno));
- MaxTasks = SEM_VALUE_MAX;
- }
- }
-
- #endif // THREADS or CYGWIN
-
- #else // _WIN32
-
- if (!(Semaphore = CreateSemaphoreA(NULL, MaxTasks, MaxTasks, NULL)))
- {
- printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(GetLastError()));
- MaxTasks = SEM_VALUE_MAX;
- }
-
- #endif // _WIN32
- }
-}
-#endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
-
-
-#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-int setupListeningSockets()
-{
- int o;
- uint_fast8_t allocsockets = maxsockets ? maxsockets : 2;
-
- SocketList = (SOCKET*)vlmcsd_malloc((size_t)allocsockets * sizeof(SOCKET));
-
- haveIPv4Stack = checkProtocolStack(AF_INET);
- haveIPv6Stack = checkProtocolStack(AF_INET6);
-
- // Reset getopt since we've alread used it
- optReset();
-
- for (opterr = 0; ( o = getopt(global_argc, (char* const*)global_argv, optstring) ) > 0; ) switch (o)
- {
- case '4':
-
- if (!haveIPv4Stack)
- {
- printerrorf("Fatal: Your system does not support %s.\n", cIPv4);
- return !0;
- }
- v4required = 1;
- break;
-
- case '6':
-
- if (!haveIPv6Stack)
- {
- printerrorf("Fatal: Your system does not support %s.\n", cIPv6);
- return !0;
- }
- v6required = 1;
- break;
-
- case 'L':
-
- addListeningSocket(optarg);
- break;
-
- case 'P':
-
- defaultport = optarg;
- break;
-
- default:
-
- break;
- }
-
-
-# ifndef NO_INI_FILE
- if (maxsockets && !numsockets)
- {
- if (fn_ini && !readIniFile(INI_FILE_PASS_2))
- {
- #ifdef INI_FILE
- if (strcmp(fn_ini, INI_FILE))
- #endif // INI_FILE
- printerrorf("Warning: Can't read %s: %s\n", fn_ini, strerror(errno));
- }
- }
-# endif
-
- // if -L hasn't been specified on the command line, use default sockets (all IP addresses)
- // maxsocket results from first pass parsing the arguments
- if (!maxsockets)
- {
- if (haveIPv6Stack && (v6required || !v4required)) addListeningSocket("::");
- if (haveIPv4Stack && (v4required || !v6required)) addListeningSocket("0.0.0.0");
- }
-
- if (!numsockets)
- {
- printerrorf("Fatal: Could not listen on any socket.\n");
- return(!0);
- }
-
- return 0;
-}
-#endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
-
-int server_main(int argc, CARGV argv)
-{
- #if !defined(_NTSERVICE) && !defined(NO_SOCKETS)
- int error;
- #endif // !defined(_NTSERVICE) && !defined(NO_SOCKETS)
-
- // Initialize ePID / HwId parameters
- memset(KmsResponseParameters, 0, sizeof(KmsResponseParameters));
-
- global_argc = argc;
- global_argv = argv;
-
- #ifdef _NTSERVICE // #endif is in newmain()
- DWORD lasterror = ERROR_SUCCESS;
-
- if (!StartServiceCtrlDispatcher(NTServiceDispatchTable) && (lasterror = GetLastError()) == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
- {
- IsNTService = FALSE;
- return newmain();
- }
-
- return lasterror;
-}
-
-
-int newmain()
-{
- int error;
-
- // Initialize thread synchronization objects for Windows and Cygwin
- #ifdef USE_THREADS
-
- #ifndef NO_LOG
- // Initialize the Critical Section for proper logging
- InitializeCriticalSection(&logmutex);
- #endif // NO_LOG
-
- #endif // USE_THREADS
-
- #ifdef _WIN32
-
- #ifndef USE_MSRPC
- // Windows Sockets must be initialized
- WSADATA wsadata;
-
- if ((error = WSAStartup(0x0202, &wsadata)))
- {
- printerrorf("Fatal: Could not initialize Windows sockets (Error: %d).\n", error);
- return error;
- }
- #endif // USE_MSRPC
-
- // Windows can never daemonize
- nodaemon = 1;
-
- #else // __CYGWIN__
-
- // Do not daemonize if we are a Windows service
- if (IsNTService) nodaemon = 1;
-
- #endif // _WIN32 / __CYGWIN__
- #endif // _NTSERVICE ( #ifdef is main(int argc, CARGV argv) )
-
- parseGeneralArguments(); // Does not return if an error occurs
-
- #if !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- struct stat statbuf;
- fstat(STDIN_FILENO, &statbuf);
- if (S_ISSOCK(statbuf.st_mode))
- {
- InetdMode = 1;
- nodaemon = 1;
- maxsockets = 0;
- #ifndef NO_LOG
- logstdout = 0;
- #endif // NO_LOG
- }
- #endif // !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
- #ifndef NO_INI_FILE
- if (fn_ini && !readIniFile(INI_FILE_PASS_1))
- {
- #ifdef INI_FILE
- if (strcmp(fn_ini, INI_FILE))
- #endif // INI_FILE
- printerrorf("Warning: Can't read %s: %s\n", fn_ini, strerror(errno));
- }
- #endif // NO_INI_FILE
-
- #if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__ && !defined(USE_MSRPC)
- allocateSemaphore();
- #endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && __minix__
-
- #ifdef _NTSERVICE
- if (installService)
- return NtServiceInstallation(installService, ServiceUser, ServicePassword);
- #endif // _NTSERVICE
-
- #if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- if (!InetdMode)
- {
- if ((error = setupListeningSockets())) return error;
- }
- #endif // NO_SOCKETS
-
- // After sockets have been set up, we may switch to a lower privileged user
- #if !defined(_WIN32) && !defined(NO_USER_SWITCH)
-
- #ifndef NO_SIGHUP
- if (!IsRestarted)
- {
- #endif // NO_SIGHUP
- if (gid != INVALID_GID && setgid(gid))
- {
- printerrorf("Fatal: setgid for %s failed.\n", gname);
- return !0;
- }
-
- if (uid != INVALID_UID && setuid(uid))
- {
- printerrorf("Fatal: setuid for %s failed.\n", uname);
- return !0;
- }
- #ifndef NO_SIGHUP
- }
- #endif // NO_SIGHUP
-
- #endif // !defined(_WIN32) && !defined(NO_USER_SWITCH)
-
- randomNumberInit();
-
- // Randomization Level 1 means generate ePIDs at startup and use them during
- // the lifetime of the process. So we generate them now
- #ifndef NO_RANDOM_EPID
- if (RandomizationLevel == 1) randomPidInit();
- #endif
-
- #if !defined(NO_SOCKETS)
- #ifdef _WIN32
- if (!IsNTService)
- #endif // _WIN32
- if ((error = daemonizeAndSetSignalAction())) return error;
- #endif // !defined(NO_SOCKETS)
-
- writePidFile();
-
- #if !defined(NO_LOG) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- if (!InetdMode)
- logger("vlmcsd %s started successfully\n", Version);
- #endif // !defined(NO_LOG) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
- #if defined(_NTSERVICE) && !defined(USE_MSRPC)
- if (IsNTService) ReportServiceStatus(SERVICE_RUNNING, NO_ERROR, 200);
- #endif // defined(_NTSERVICE) && !defined(USE_MSRPC)
-
- int rc;
- rc = runServer();
-
- // Clean up things and exit
- #ifdef _NTSERVICE
- if (!ServiceShutdown)
- #endif
- cleanup();
- #ifdef _NTSERVICE
- else
- ReportServiceStatus(SERVICE_STOPPED, NO_ERROR, 0);
- #endif
-
- return rc;
-}
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "crypto.h"
-#include "endian.h"
-#include
-
-const BYTE AesKeyV4[] = {
- 0x05, 0x3D, 0x83, 0x07, 0xF9, 0xE5, 0xF0, 0x88, 0xEB, 0x5E, 0xA6, 0x68, 0x6C, 0xF0, 0x37, 0xC7, 0xE4, 0xEF, 0xD2, 0xD6};
-
-const BYTE AesKeyV5[] = {
- 0xCD, 0x7E, 0x79, 0x6F, 0x2A, 0xB2, 0x5D, 0xCB, 0x55, 0xFF, 0xC8, 0xEF, 0x83, 0x64, 0xC4, 0x70 };
-
-const BYTE AesKeyV6[] = {
- 0xA9, 0x4A, 0x41, 0x95, 0xE2, 0x01, 0x43, 0x2D, 0x9B, 0xCB, 0x46, 0x04, 0x05, 0xD8, 0x4A, 0x21 };
-
-static const BYTE SBox[] = {
- 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
- 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
- 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
- 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
- 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
- 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
- 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
- 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
- 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
- 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
- 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
- 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
- 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
- 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
- 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
- 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
- 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
- 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
- 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
- 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
- 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
- 0xB0, 0x54, 0xBB, 0x16
-};
-
-
-void XorBlock(const BYTE *const in, const BYTE *out) // Ensure that this is always 32 bit aligned
-{
- /*UAA64( out, 0 ) ^= UAA64( in, 0 );
- UAA64( out, 1 ) ^= UAA64( in, 1 );*/
-
- uint_fast8_t i;
-
- for (i = 0; i < AES_BLOCK_WORDS; i++)
- {
- ((DWORD*)out)[i] ^= ((DWORD*)in)[i];
- }
-}
-
-#define AddRoundKey(d, rk) XorBlock((const BYTE *)rk, (const BYTE *)d)
-
-#define Mul2(word) (((word & 0x7f7f7f7f) << 1) ^ (((word & 0x80808080) >> 7) * 0x1b))
-#define Mul3(word) (Mul2(word) ^ word)
-#define Mul4(word) (Mul2(Mul2(word)))
-#define Mul8(word) (Mul2(Mul2(Mul2(word))))
-#define Mul9(word) (Mul8(word) ^ word)
-#define MulB(word) (Mul8(word) ^ Mul3(word))
-#define MulD(word) (Mul8(word) ^ Mul4(word) ^ word)
-#define MulE(word) (Mul8(word) ^ Mul4(word) ^ Mul2(word))
-
-//32 bit Galois Multiplication (generates bigger code than Macros)
-/*static DWORD Mul(DWORD x, DWORD y)
-{
- DWORD result = x, yTemp = y, log2;
-
- if (!y) return 0;
-
- for (log2 = 0; yTemp >>= 1; log2++ )
- {
- result = Mul2(result);
- }
-
- return result ^ Mul(x, y - (1 << log2));
-}*/
-
-
-void MixColumnsR(BYTE *restrict state)
-{
- uint_fast8_t i = 0;
- for (; i < AES_BLOCK_WORDS; i++)
- {
- #if defined(_CRYPTO_OPENSSL) && defined(_OPENSSL_SOFTWARE) && defined(_USE_AES_FROM_OPENSSL) //Always byte swap regardless of endianess
- DWORD word = BS32(((DWORD *) state)[i]);
- ((DWORD *) state)[i] = BS32(MulE(word) ^ ROR32(MulB(word), 8) ^ ROR32(MulD(word), 16) ^ ROR32(Mul9(word), 24));
- #else
- DWORD word = LE32(((DWORD *) state)[i]);
- ((DWORD *) state)[i] = LE32(MulE(word) ^ ROR32(MulB(word), 8) ^ ROR32(MulD(word), 16) ^ ROR32(Mul9(word), 24));
- #endif
- }
-}
-
-
-static DWORD SubDword(DWORD v)
-{
- BYTE *b = (BYTE *)&v;
- uint_fast8_t i = 0;
-
- for (; i < sizeof(DWORD); i++) b[i] = SBox[b[i]];
-
- return v;
-}
-
-
-void AesInitKey(AesCtx *Ctx, const BYTE *Key, int_fast8_t IsV6, int RijndaelKeyBytes)
-{
- int RijndaelKeyDwords = RijndaelKeyBytes / sizeof(DWORD);
- Ctx->rounds = (uint_fast8_t)(RijndaelKeyDwords + 6);
-
- static const DWORD RCon[] = {
- 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
- 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000 };
-
- uint_fast8_t i;
- DWORD temp;
-
- memcpy(Ctx->Key, Key, RijndaelKeyBytes);
-
- for ( i = RijndaelKeyDwords; i < ( Ctx->rounds + 1 ) << 2; i++ )
- {
- temp = Ctx->Key[ i - 1 ];
-
- if ( ( i % RijndaelKeyDwords ) == 0 )
- temp = BE32( SubDword( ROR32( BE32(temp), 24) ) ^ RCon[ i / RijndaelKeyDwords ] );
-
- Ctx->Key[ i ] = Ctx->Key[ i - RijndaelKeyDwords ] ^ temp;
- }
-
- if ( IsV6 )
- {
- BYTE *_p = (BYTE *)Ctx->Key;
-
- _p[ 4 * 16 ] ^= 0x73;
- _p[ 6 * 16 ] ^= 0x09;
- _p[ 8 * 16 ] ^= 0xE4;
- }
-}
-
-
-#if !defined(_CRYPTO_OPENSSL) || !defined(_USE_AES_FROM_OPENSSL) || defined(_OPENSSL_SOFTWARE)
-static void SubBytes(BYTE *block)
-{
- uint_fast8_t i;
-
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- block[i] = SBox[ block[i] ];
-}
-
-
-static void ShiftRows(BYTE *state)
-{
- BYTE bIn[AES_BLOCK_BYTES];
- uint_fast8_t i;
-
- memcpy(bIn, state, AES_BLOCK_BYTES);
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- {
- state[i] = bIn[(i + ((i & 3) << 2)) & 0xf];
- }
-};
-
-
-static void MixColumns(BYTE *state)
-{
- uint_fast8_t i = 0;
- for (; i < AES_BLOCK_WORDS; i++)
- {
- DWORD word = LE32(((DWORD *) state)[i]);
- ((DWORD *) state)[i] = LE32(Mul2(word) ^ ROR32(Mul3(word), 8) ^ ROR32(word, 16) ^ ROR32(word, 24));
- }
-}
-
-
-void AesEncryptBlock(const AesCtx *const Ctx, BYTE *block)
-{
- uint_fast8_t i;
-
- for ( i = 0 ;; i += 4 )
- {
- AddRoundKey(block, &Ctx->Key[ i ]);
- SubBytes(block);
- ShiftRows(block);
-
- if ( i >= ( Ctx->rounds - 1 ) << 2 ) break;
-
- MixColumns(block);
- }
-
- AddRoundKey(block, &Ctx->Key[ Ctx->rounds << 2 ]);
-}
-
-
-void AesCmacV4(BYTE *Message, size_t MessageSize, BYTE *MacOut)
-{
- size_t i;
- BYTE mac[AES_BLOCK_BYTES];
- AesCtx Ctx;
-
- AesInitKey(&Ctx, AesKeyV4, FALSE, V4_KEY_BYTES);
-
- memset(mac, 0, sizeof(mac));
- memset(Message + MessageSize, 0, AES_BLOCK_BYTES);
- Message[MessageSize] = 0x80;
-
- for (i = 0; i <= MessageSize; i += AES_BLOCK_BYTES)
- {
- XorBlock(Message + i, mac);
- AesEncryptBlock(&Ctx, mac);
- }
-
- memcpy(MacOut, mac, AES_BLOCK_BYTES);
-}
-#endif
-
-#if !defined(_CRYPTO_OPENSSL) || !defined(_USE_AES_FROM_OPENSSL)
-
-static const BYTE SBoxR[] = {
- 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,
- 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
- 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,
- 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
- 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,
- 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
- 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
- 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
- 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,
- 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
- 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
- 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
- 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,
- 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
- 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,
- 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
- 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,
- 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
- 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,
- 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
- 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
- 0x55, 0x21, 0x0C, 0x7D
-};
-
-
-static void ShiftRowsR(BYTE *state)
-{
- BYTE b[AES_BLOCK_BYTES];
- uint_fast8_t i;
-
- memcpy(b, state, AES_BLOCK_BYTES);
-
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- state[i] = b[(i - ((i & 0x3) << 2)) & 0xf];
-}
-
-
-static void SubBytesR(BYTE *block)
-{
- uint_fast8_t i;
-
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- block[i] = SBoxR[ block[i] ];
-}
-
-
-void AesEncryptCbc(const AesCtx *const Ctx, BYTE *restrict iv, BYTE *restrict data, size_t *restrict len)
-{
- // Pad up to blocksize inclusive
- size_t i;
- uint_fast8_t pad = (~*len & (AES_BLOCK_BYTES - 1)) + 1;
-
- #if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ == 8) // gcc 4.8 memset bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56977
- for (i = 0; i < pad; i++) data[*len + i] = pad;
- #else
- memset(data + *len, pad, pad);
- #endif
- *len += pad;
-
- if ( iv ) XorBlock(iv, data);
- AesEncryptBlock(Ctx, data);
-
- for (i = *len - AES_BLOCK_BYTES; i; i -= AES_BLOCK_BYTES)
- {
- XorBlock(data, data + AES_BLOCK_BYTES);
- data += AES_BLOCK_BYTES;
- AesEncryptBlock(Ctx, data);
- }
-}
-
-
-void AesDecryptBlock(const AesCtx *const Ctx, BYTE *block)
-{
- uint_fast8_t i;
-
- AddRoundKey(block, &Ctx->Key[ Ctx->rounds << 2 ]);
-
- for ( i = ( Ctx->rounds - 1 ) << 2 ;; i -= 4 )
- {
- ShiftRowsR(block);
- SubBytesR(block);
- AddRoundKey(block, &Ctx->Key[ i ]);
-
- if ( i == 0 ) break;
-
- MixColumnsR(block);
- }
-}
-
-
-void AesDecryptCbc(const AesCtx *const Ctx, BYTE *iv, BYTE *data, size_t len)
-{
- BYTE *cc;
-
- for (cc = data + len - AES_BLOCK_BYTES; cc > data; cc -= AES_BLOCK_BYTES)
- {
- AesDecryptBlock(Ctx, cc);
- XorBlock(cc - AES_BLOCK_BYTES, cc);
- }
-
- AesDecryptBlock(Ctx, cc);
- if ( iv ) XorBlock(iv, cc);
-}
-#endif // _CRYPTO_OPENSSL || OPENSSL_VERSION_NUMBER < 0x10000000L
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include
-#include
-#include
-#include
-#include
-#if !defined(_WIN32)
-#include
-#endif
-
-#include "output.h"
-#include "crypto.h"
-#include "endian.h"
-#include "kms.h"
-#include "shared_globals.h"
-#include "helpers.h"
-
-#define FRIENDLY_NAME_WINDOWS "Windows"
-#define FRIENDLY_NAME_OFFICE2010 "Office 2010"
-#define FRIENDLY_NAME_OFFICE2013 "Office"
-
-#ifndef NO_BASIC_PRODUCT_LIST
-// Do not change the order of this list. Append items as necessary
-const KmsIdList ProductList[] = {
- /* 000 */ { { 0x212a64dc, 0x43b1, 0x4d3d, { 0xa3, 0x0c, 0x2f, 0xc6, 0x9d, 0x20, 0x95, 0xc6 } } /*"212a64dc-43b1-4d3d-a30c-2fc69d2095c6"*/, "Vista", EPID_WINDOWS, 4, 25 },
- /* 001 */ { { 0x7fde5219, 0xfbfa, 0x484a, { 0x82, 0xc9, 0x34, 0xd1, 0xad, 0x53, 0xe8, 0x56 } } /*"7fde5219-fbfa-484a-82c9-34d1ad53e856"*/, "Windows 7", EPID_WINDOWS, 4, 25 },
- /* 002 */ { { 0x3c40b358, 0x5948, 0x45af, { 0x92, 0x3b, 0x53, 0xd2, 0x1f, 0xcc, 0x7e, 0x79 } } /*"3c40b358-5948-45af-923b-53d21fcc7e79"*/, "Windows 8 VL", EPID_WINDOWS, 5, 25 },
- /* 003 */ { { 0x5f94a0bb, 0xd5a0, 0x4081, { 0xa6, 0x85, 0x58, 0x19, 0x41, 0x8b, 0x2f, 0xe0 } } /*"5f94a0bb-d5a0-4081-a685-5819418b2fe0"*/, "Windows Preview", EPID_WINDOWS, 6, 25 },
- /* 004 */ { { 0xbbb97b3b, 0x8ca4, 0x4a28, { 0x97, 0x17, 0x89, 0xfa, 0xbd, 0x42, 0xc4, 0xac } } /*"bbb97b3b-8ca4-4a28-9717-89fabd42c4ac"*/, "Windows 8 Retail", EPID_WINDOWS, 5, 25 },
- /* 005 */ { { 0xcb8fc780, 0x2c05, 0x495a, { 0x97, 0x10, 0x85, 0xaf, 0xff, 0xc9, 0x04, 0xd7 } } /*"cb8fc780-2c05-495a-9710-85afffc904d7"*/, "Windows 8.1 VL", EPID_WINDOWS, 6, 25 },
- /* 006 */ { { 0x6d646890, 0x3606, 0x461a, { 0x86, 0xab, 0x59, 0x8b, 0xb8, 0x4a, 0xce, 0x82 } } /*"6d646890-3606-461a-86ab-598bb84ace82"*/, "Windows 8.1 Retail", EPID_WINDOWS, 6, 25 },
- /* 007 */ { { 0x33e156e4, 0xb76f, 0x4a52, { 0x9f, 0x91, 0xf6, 0x41, 0xdd, 0x95, 0xac, 0x48 } } /*"33e156e4-b76f-4a52-9f91-f641dd95ac48"*/, "Windows 2008 A", EPID_WINDOWS, 4, 5 },
- /* 008 */ { { 0x8fe53387, 0x3087, 0x4447, { 0x89, 0x85, 0xf7, 0x51, 0x32, 0x21, 0x5a, 0xc9 } } /*"8fe53387-3087-4447-8985-f75132215ac9"*/, "Windows 2008 B", EPID_WINDOWS, 4, 5 },
- /* 009 */ { { 0x8a21fdf3, 0xcbc5, 0x44eb, { 0x83, 0xf3, 0xfe, 0x28, 0x4e, 0x66, 0x80, 0xa7 } } /*"8a21fdf3-cbc5-44eb-83f3-fe284e6680a7"*/, "Windows 2008 C", EPID_WINDOWS, 4, 5 },
- /* 010 */ { { 0x0fc6ccaf, 0xff0e, 0x4fae, { 0x9d, 0x08, 0x43, 0x70, 0x78, 0x5b, 0xf7, 0xed } } /*"0fc6ccaf-ff0e-4fae-9d08-4370785bf7ed"*/, "Windows 2008 R2 A", EPID_WINDOWS, 4, 5 },
- /* 011 */ { { 0xca87f5b6, 0xcd46, 0x40c0, { 0xb0, 0x6d, 0x8e, 0xcd, 0x57, 0xa4, 0x37, 0x3f } } /*"ca87f5b6-cd46-40c0-b06d-8ecd57a4373f"*/, "Windows 2008 R2 B", EPID_WINDOWS, 4, 5 },
- /* 012 */ { { 0xb2ca2689, 0xa9a8, 0x42d7, { 0x93, 0x8d, 0xcf, 0x8e, 0x9f, 0x20, 0x19, 0x58 } } /*"b2ca2689-a9a8-42d7-938d-cf8e9f201958"*/, "Windows 2008 R2 C", EPID_WINDOWS, 4, 5 },
- /* 013 */ { { 0x8665cb71, 0x468c, 0x4aa3, { 0xa3, 0x37, 0xcb, 0x9b, 0xc9, 0xd5, 0xea, 0xac } } /*"8665cb71-468c-4aa3-a337-cb9bc9d5eaac"*/, "Windows 2012", EPID_WINDOWS, 5, 5 },
- /* 014 */ { { 0x8456EFD3, 0x0C04, 0x4089, { 0x87, 0x40, 0x5b, 0x72, 0x38, 0x53, 0x5a, 0x65 } } /*"8456EFD3-0C04-4089-8740-5B7238535A65"*/, "Windows 2012 R2", EPID_WINDOWS, 6, 5 },
- /* 015 */ { { 0xe85af946, 0x2e25, 0x47b7, { 0x83, 0xe1, 0xbe, 0xbc, 0xeb, 0xea, 0xc6, 0x11 } } /*"e85af946-2e25-47b7-83e1-bebcebeac611"*/, "Office 2010", EPID_OFFICE2010, 4, 5 },
- /* 016 */ { { 0xe6a6f1bf, 0x9d40, 0x40c3, { 0xaa, 0x9f, 0xc7, 0x7b, 0xa2, 0x15, 0x78, 0xc0 } } /*"e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0"*/, "Office 2013", EPID_OFFICE2013, 6, 5 },
- /* 017 */ { { 0x6d5f5270, 0x31ac, 0x433e, { 0xb9, 0x0a, 0x39, 0x89, 0x29, 0x23, 0xc6, 0x57 } } /*"6d5f5270-31ac-433e-b90a-39892923c657"*/, "Windows Server Preview", EPID_WINDOWS, 6, 5 },
- /* 018 */ { { 0x85b5f61b, 0x320b, 0x4be3, { 0x81, 0x4a, 0xb7, 0x6b, 0x2b, 0xfa, 0xfc, 0x82 } } /*"85b5f61b-320b-4be3-814a-b76b2bfafc82"*/, "Office 2016", EPID_OFFICE2013, 6, 5 },
- /* 019 */ { { 0x58e2134f, 0x8e11, 0x4d17, { 0x9c, 0xb2, 0x91, 0x06, 0x9c, 0x15, 0x11, 0x48 } } /*"58e2134f-8e11-4d17-9cb2-91069c151148"*/, "Windows 10 VL", EPID_WINDOWS, 6, 25 },
- /* 020 */ { { 0xe1c51358, 0xfe3e, 0x4203, { 0xa4, 0xa2, 0x3b, 0x6b, 0x20, 0xc9, 0x73, 0x4e } } /*"e1c51358-fe3e-4203-a4a2-3b6b20c9734e"*/, "Windows 10 Retail", EPID_WINDOWS, 6, 25 },
- /* 021 */ { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
-};
-#endif
-
-// Application ID is used by KMS server to count KeyManagementServiceCurrentCount
-// Do not change the order of this list. Append items as necessary
-const KmsIdList AppList[] = {
- /* 000 */ { { 0x55c92734, 0xd682, 0x4d71, { 0x98, 0x3e, 0xd6, 0xec, 0x3f, 0x16, 0x05, 0x9f } } /*"55C92734-D682-4D71-983E-D6EC3F16059F"*/, FRIENDLY_NAME_WINDOWS, EPID_WINDOWS, 0, 0},
- /* 001 */ { { 0x59A52881, 0xa989, 0x479d, { 0xaf, 0x46, 0xf2, 0x75, 0xc6, 0x37, 0x06, 0x63 } } /*"59A52881-A989-479D-AF46-F275C6370663"*/, FRIENDLY_NAME_OFFICE2010, EPID_OFFICE2010, 0, 0},
- /* 002 */ { { 0x0FF1CE15, 0xA989, 0x479D, { 0xaf, 0x46, 0xf2, 0x75, 0xc6, 0x37, 0x06, 0x63 } } /*"0FF1CE15-A989-479D-AF46-F275C6370663"*/, FRIENDLY_NAME_OFFICE2013, EPID_OFFICE2013, 0, 0},
- /* 003 */ { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
-};
-
-#ifndef NO_EXTENDED_PRODUCT_LIST
-const KmsIdList ExtendedProductList [] = {
-
- // Windows Server
-
- { { 0xad2542d4, 0x9154, 0x4c6d, { 0x8a, 0x44, 0x30, 0xf1, 0x1e, 0xe9, 0x69, 0x89, } } /*ad2542d4-9154-4c6d-8a44-30f11ee96989*/, "Windows Server 2008 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008A },
- { { 0x2401e3d0, 0xc50a, 0x4b58, { 0x87, 0xb2, 0x7e, 0x79, 0x4b, 0x7d, 0x26, 0x07, } } /*2401e3d0-c50a-4b58-87b2-7e794b7d2607*/, "Windows Server 2008 Standard V", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008A },
- { { 0x68b6e220, 0xcf09, 0x466b, { 0x92, 0xd3, 0x45, 0xcd, 0x96, 0x4b, 0x95, 0x09, } } /*68b6e220-cf09-466b-92d3-45cd964b9509*/, "Windows Server 2008 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008C },
- { { 0xfd09ef77, 0x5647, 0x4eff, { 0x80, 0x9c, 0xaf, 0x2b, 0x64, 0x65, 0x9a, 0x45, } } /*fd09ef77-5647-4eff-809c-af2b64659a45*/, "Windows Server 2008 Datacenter V", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008C },
- { { 0xc1af4d90, 0xd1bc, 0x44ca, { 0x85, 0xd4, 0x00, 0x3b, 0xa3, 0x3d, 0xb3, 0xb9, } } /*c1af4d90-d1bc-44ca-85d4-003ba33db3b9*/, "Windows Server 2008 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008B },
- { { 0x8198490a, 0xadd0, 0x47b2, { 0xb3, 0xba, 0x31, 0x6b, 0x12, 0xd6, 0x47, 0xb4, } } /*8198490a-add0-47b2-b3ba-316b12d647b4*/, "Windows Server 2008 Enterprise V", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008B },
- { { 0xddfa9f7c, 0xf09e, 0x40b9, { 0x8c, 0x1a, 0xbe, 0x87, 0x7a, 0x9a, 0x7f, 0x4b, } } /*ddfa9f7c-f09e-40b9-8c1a-be877a9a7f4b*/, "Windows Server 2008 Web", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008A },
- { { 0x7afb1156, 0x2c1d, 0x40fc, { 0xb2, 0x60, 0xaa, 0xb7, 0x44, 0x2b, 0x62, 0xfe, } } /*7afb1156-2c1d-40fc-b260-aab7442b62fe*/, "Windows Server 2008 Compute Cluster", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008C },
- { { 0x68531fb9, 0x5511, 0x4989, { 0x97, 0xbe, 0xd1, 0x1a, 0x0f, 0x55, 0x63, 0x3f, } } /*68531fb9-5511-4989-97be-d11a0f55633f*/, "Windows Server 2008 R2 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2A },
- { { 0x7482e61b, 0xc589, 0x4b7f, { 0x8e, 0xcc, 0x46, 0xd4, 0x55, 0xac, 0x3b, 0x87, } } /*7482e61b-c589-4b7f-8ecc-46d455ac3b87*/, "Windows Server 2008 R2 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2C },
- { { 0x620e2b3d, 0x09e7, 0x42fd, { 0x80, 0x2a, 0x17, 0xa1, 0x36, 0x52, 0xfe, 0x7a, } } /*620e2b3d-09e7-42fd-802a-17a13652fe7a*/, "Windows Server 2008 R2 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2B },
- { { 0xa78b8bd9, 0x8017, 0x4df5, { 0xb8, 0x6a, 0x09, 0xf7, 0x56, 0xaf, 0xfa, 0x7c, } } /*a78b8bd9-8017-4df5-b86a-09f756affa7c*/, "Windows Server 2008 R2 Web", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2A },
- { { 0xcda18cf3, 0xc196, 0x46ad, { 0xb2, 0x89, 0x60, 0xc0, 0x72, 0x86, 0x99, 0x94, } } /*cda18cf3-c196-46ad-b289-60c072869994*/, "Windows Server 2008 R2 Compute Cluster", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2C },
- { { 0xd3643d60, 0x0c42, 0x412d, { 0xa7, 0xd6, 0x52, 0xe6, 0x63, 0x53, 0x27, 0xf6, } } /*d3643d60-0c42-412d-a7d6-52e6635327f6*/, "Windows Server 2012 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0xf0f5ec41, 0x0d55, 0x4732, { 0xaf, 0x02, 0x44, 0x0a, 0x44, 0xa3, 0xcf, 0x0f, } } /*f0f5ec41-0d55-4732-af02-440a44a3cf0f*/, "Windows Server 2012 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0x95fd1c83, 0x7df5, 0x494a, { 0xbe, 0x8b, 0x13, 0x00, 0xe1, 0xc9, 0xd1, 0xcd, } } /*95fd1c83-7df5-494a-be8b-1300e1c9d1cd*/, "Windows Server 2012 MultiPoint Premium", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0x7d5486c7, 0xe120, 0x4771, { 0xb7, 0xf1, 0x7b, 0x56, 0xc6, 0xd3, 0x17, 0x0c, } } /*7d5486c7-e120-4771-b7f1-7b56c6d3170c*/, "Windows Server 2012 MultiPoint Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0x00091344, 0x1ea4, 0x4f37, { 0xb7, 0x89, 0x01, 0x75, 0x0b, 0xa6, 0x98, 0x8c, } } /*00091344-1ea4-4f37-b789-01750ba6988c*/, "Windows Server 2012 R2 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0xb3ca044e, 0xa358, 0x4d68, { 0x98, 0x83, 0xaa, 0xa2, 0x94, 0x1a, 0xca, 0x99, } } /*b3ca044e-a358-4d68-9883-aaa2941aca99*/, "Windows Server 2012 R2 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0xb743a2be, 0x68d4, 0x4dd3, { 0xaf, 0x32, 0x92, 0x42, 0x5b, 0x7b, 0xb6, 0x23, } } /*b743a2be-68d4-4dd3-af32-92425b7bb623*/, "Windows Server 2012 R2 Cloud Storage", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0x21db6ba4, 0x9a7b, 0x4a14, { 0x9e, 0x29, 0x64, 0xa6, 0x0c, 0x59, 0x30, 0x1d, } } /*21db6ba4-9a7b-4a14-9e29-64a60c59301d*/, "Windows Server 2012 R2 Essentials", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0xba947c44, 0xd19d, 0x4786, { 0xb6, 0xae, 0x22, 0x77, 0x0b, 0xc9, 0x4c, 0x54, } } /*ba947c44-d19d-4786-b6ae-22770bc94c54*/, "Windows Server 2016 Datacenter Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_SRV_BETA },
-
-
- // Windows 10 Preview
-# ifdef INCLUDE_BETAS
- { { 0x6496e59d, 0x89dc, 0x49eb, { 0xa3, 0x53, 0x09, 0xce, 0xb9, 0x40, 0x48, 0x45, } } /*6496e59d-89dc-49eb-a353-09ceb9404845*/, "Windows 10 Core Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0xa4383e6b, 0xdada, 0x423d, { 0xa4, 0x3d, 0xf2, 0x56, 0x78, 0x42, 0x96, 0x76, } } /*a4383e6b-dada-423d-a43d-f25678429676*/, "Windows 10 Professional Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0xcf59a07b, 0x1a2a, 0x4be0, { 0xbf, 0xe0, 0x42, 0x3b, 0x58, 0x23, 0xe6, 0x63, } } /*cf59a07b-1a2a-4be0-bfe0-423b5823e663*/, "Windows 10 Professional WMC Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0xcde952c7, 0x2f96, 0x4d9d, { 0x8f, 0x2b, 0x2d, 0x34, 0x9f, 0x64, 0xfc, 0x51, } } /*cde952c7-2f96-4d9d-8f2b-2d349f64fc51*/, "Windows 10 Enterprise Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
-# endif
-
-
- // Windows 10
-
- { { 0x73111121, 0x5638, 0x40f6, { 0xbc, 0x11, 0xf1, 0xd7, 0xb0, 0xd6, 0x43, 0x00, } } /*73111121-5638-40f6-bc11-f1d7b0d64300*/, "Windows 10 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL },
- { { 0xe272e3e2, 0x732f, 0x4c65, { 0xa8, 0xf0, 0x48, 0x47, 0x47, 0xd0, 0xd9, 0x47, } } /*e272e3e2-732f-4c65-a8f0-484747d0d947*/, "Windows 10 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x7b51a46c, 0x0c04, 0x4e8f, { 0x9a, 0xf4, 0x84, 0x96, 0xcc, 0xa9, 0x0d, 0x5e, } } /*7b51a46c-0c04-4e8f-9af4-8496cca90d5e*/, "Windows 10 Enterprise LTSB", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x87b838b7, 0x41b6, 0x4590, { 0x83, 0x18, 0x57, 0x97, 0x95, 0x1d, 0x85, 0x29, } } /*87b838b7-41b6-4590-8318-5797951d8529*/, "Windows 10 Enterprise LTSB N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0xe0c42288, 0x980c, 0x4788, { 0xa0, 0x14, 0xc0, 0x80, 0xd2, 0xe1, 0x92, 0x6e, } } /*e0c42288-980c-4788-a014-c080d2e1926e*/, "Windows 10 Education", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x3c102355, 0xd027, 0x42c6, { 0xad, 0x23, 0x2e, 0x7e, 0xf8, 0xa0, 0x25, 0x85, } } /*3c102355-d027-42c6-ad23-2e7ef8a02585*/, "Windows 10 Education N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x2de67392, 0xb7a7, 0x462a, { 0xb1, 0xca, 0x10, 0x8d, 0xd1, 0x89, 0xf5, 0x88, } } /*2de67392-b7a7-462a-b1ca-108dd189f588*/, "Windows 10 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL },
- { { 0xa80b5abf, 0x75ad, 0x428b, { 0xb0, 0x5d, 0xa4, 0x7d, 0x2d, 0xff, 0xee, 0xbf, } } /*a80b5abf-76ad-428b-b05d-a47d2dffeebf*/, "Windows 10 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x58e97c99, 0xf377, 0x4ef1, { 0x81, 0xd5, 0x4a, 0xd5, 0x52, 0x2b, 0x5f, 0xd8, } } /*58e97c99-f377-4ef1-81d5-4ad5522b5fd8*/, "Windows 10 Home", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
- { { 0x7b9e1751, 0xa8da, 0x4f75, { 0x95, 0x60, 0x5f, 0xad, 0xfe, 0x3d, 0x8e, 0x38, } } /*7b9e1751-a8da-4f75-9560-5fadfe3d8e38*/, "Windows 10 Home N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
- { { 0xcd918a57, 0xa41b, 0x4c82, { 0x8d, 0xce, 0x1a, 0x53, 0x8e, 0x22, 0x1a, 0x83, } } /*cd918a57-a41b-4c82-8dce-1a538e221a83*/, "Windows 10 Home Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
- { { 0xa9107544, 0xf4a0, 0x4053, { 0xa9, 0x6a, 0x14, 0x79, 0xab, 0xde, 0xf9, 0x12, } } /*a9107544-f4a0-4053-a96a-1479abdef912*/, "Windows 10 Home Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
-
-
- // Windows 8.x
-
-# ifdef INCLUDE_BETAS
- { { 0x2B9C337F, 0x7A1D, 0x4271, { 0x90, 0xA3, 0xC6, 0x85, 0x5A, 0x2B, 0x8A, 0x1C, } } /*2B9C337F-7A1D-4271-90A3-C6855A2B8A1C*/, "Windows 8.x Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0x631EAD72, 0xA8AB, 0x4DF8, { 0xBB, 0xDF, 0x37, 0x20, 0x29, 0x98, 0x9B, 0xDD, } } /*631EAD72-A8AB-4DF8-BBDF-372029989BDD*/, "Windows 8.x Preview ARM", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
-# endif
- { { 0x81671aaf, 0x79d1, 0x4eb1, { 0xb0, 0x04, 0x8c, 0xbb, 0xe1, 0x73, 0xaf, 0xea, } } /*81671aaf-79d1-4eb1-b004-8cbbe173afea*/, "Windows 8.1 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0x113e705c, 0xfa49, 0x48a4, { 0xbe, 0xea, 0x7d, 0xd8, 0x79, 0xb4, 0x6b, 0x14, } } /*113e705c-fa49-48a4-beea-7dd879b46b14*/, "Windows 8.1 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0x096ce63d, 0x4fac, 0x48a9, { 0x82, 0xa9, 0x61, 0xae, 0x9e, 0x80, 0x0e, 0x5f, } } /*096ce63d-4fac-48a9-82a9-61ae9e800e5f*/, "Windows 8.1 Professional WMC", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xc06b6981, 0xd7fd, 0x4a35, { 0xb7, 0xb4, 0x05, 0x47, 0x42, 0xb7, 0xaf, 0x67, } } /*c06b6981-d7fd-4a35-b7b4-054742b7af67*/, "Windows 8.1 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0x7476d79f, 0x8e48, 0x49b4, { 0xab, 0x63, 0x4d, 0x0b, 0x81, 0x3a, 0x16, 0xe4, } } /*7476d79f-8e48-49b4-ab63-4d0b813a16e4*/, "Windows 8.1 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xfe1c3238, 0x432a, 0x43a1, { 0x8e, 0x25, 0x97, 0xe7, 0xd1, 0xef, 0x10, 0xf3, } } /*fe1c3238-432a-43a1-8e25-97e7d1ef10f3*/, "Windows 8.1 Core", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0x78558a64, 0xdc19, 0x43fe, { 0xa0, 0xd0, 0x80, 0x75, 0xb2, 0xa3, 0x70, 0xa3, } } /*78558a64-dc19-43fe-a0d0-8075b2a370a3*/, "Windows 8.1 Core N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xffee456a, 0xcd87, 0x4390, { 0x8e, 0x07, 0x16, 0x14, 0x6c, 0x67, 0x2f, 0xd0, } } /*ffee456a-cd87-4390-8e07-16146c672fd0*/, "Windows 8.1 Core ARM", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xc72c6a1d, 0xf252, 0x4e7e, { 0xbd, 0xd1, 0x3f, 0xca, 0x34, 0x2a, 0xcb, 0x35, } } /*c72c6a1d-f252-4e7e-bdd1-3fca342acb35*/, "Windows 8.1 Core Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xdb78b74f, 0xef1c, 0x4892, { 0xab, 0xfe, 0x1e, 0x66, 0xb8, 0x23, 0x1d, 0xf6, } } /*db78b74f-ef1c-4892-abfe-1e66b8231df6*/, "Windows 8.1 Core Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xe9942b32, 0x2e55, 0x4197, { 0xb0, 0xbd, 0x5f, 0xf5, 0x8c, 0xba, 0x88, 0x60, } } /*e9942b32-2e55-4197-b0bd-5ff58cba8860*/, "Windows 8.1 Core Connected", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xc6ddecd6, 0x2354, 0x4c19, { 0x90, 0x9b, 0x30, 0x6a, 0x30, 0x58, 0x48, 0x4e, } } /*c6ddecd6-2354-4c19-909b-306a3058484e*/, "Windows 8.1 Core Connected N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xb8f5e3a3, 0xed33, 0x4608, { 0x81, 0xe1, 0x37, 0xd6, 0xc9, 0xdc, 0xfd, 0x9c, } } /*b8f5e3a3-ed33-4608-81e1-37d6c9dcfd9c*/, "Windows 8.1 Core Connected Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xba998212, 0x460a, 0x44db, { 0xbf, 0xb5, 0x71, 0xbf, 0x09, 0xd1, 0xc6, 0x8b, } } /*ba998212-460a-44db-bfb5-71bf09d1c68b*/, "Windows 8.1 Core Connected Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xe58d87b5, 0x8126, 0x4580, { 0x80, 0xfb, 0x86, 0x1b, 0x22, 0xf7, 0x92, 0x96, } } /*e58d87b5-8126-4580-80fb-861b22f79296*/, "Windows 8.1 Professional Student", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xcab491c7, 0xa918, 0x4f60, { 0xb5, 0x02, 0xda, 0xb7, 0x5e, 0x33, 0x4f, 0x40, } } /*cab491c7-a918-4f60-b502-dab75e334f40*/, "Windows 8.1 Professional Student N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xa00018a3, 0xf20f, 0x4632, { 0xbf, 0x7c, 0x8d, 0xaa, 0x53, 0x51, 0xc9, 0x14, } } /*a00018a3-f20f-4632-bf7c-8daa5351c914*/, "Windows 8 Professional WMC", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0xa98bcd6d, 0x5343, 0x4603, { 0x8a, 0xfe, 0x59, 0x08, 0xe4, 0x61, 0x11, 0x12, } } /*a98bcd6d-5343-4603-8afe-5908e4611112*/, "Windows 8 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0xebf245c1, 0x29a8, 0x4daf, { 0x9c, 0xb1, 0x38, 0xdf, 0xc6, 0x08, 0xa8, 0xc8, } } /*ebf245c1-29a8-4daf-9cb1-38dfc608a8c8*/, "Windows 8 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0x458e1bec, 0x837a, 0x45f6, { 0xb9, 0xd5, 0x92, 0x5e, 0xd5, 0xd2, 0x99, 0xde, } } /*458e1bec-837a-45f6-b9d5-925ed5d299de*/, "Windows 8 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0xe14997e7, 0x800a, 0x4cf7, { 0xad, 0x10, 0xde, 0x4b, 0x45, 0xb5, 0x78, 0xdb, } } /*e14997e7-800a-4cf7-ad10-de4b45b578db*/, "Windows 8 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0xc04ed6bf, 0x55c8, 0x4b47, { 0x9f, 0x8e, 0x5a, 0x1f, 0x31, 0xce, 0xee, 0x60, } } /*c04ed6bf-55c8-4b47-9f8e-5a1f31ceee60*/, "Windows 8 Core", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0x197390a0, 0x65f6, 0x4a95, { 0xbd, 0xc4, 0x55, 0xd5, 0x8a, 0x3b, 0x02, 0x53, } } /*197390a0-65f6-4a95-bdc4-55d58a3b0253*/, "Windows 8 Core N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0x9d5584a2, 0x2d85, 0x419a, { 0x98, 0x2c, 0xa0, 0x08, 0x88, 0xbb, 0x9d, 0xdf, } } /*9d5584a2-2d85-419a-982c-a00888bb9ddf*/, "Windows 8 Core Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0x8860fcd4, 0xa77b, 0x4a20, { 0x90, 0x45, 0xa1, 0x50, 0xff, 0x11, 0xd6, 0x09, } } /*8860fcd4-a77b-4a20-9045-a150ff11d609*/, "Windows 8 Core Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
-
-
- // Windows 7
-
- { { 0xae2ee509, 0x1b34, 0x41c0, { 0xac, 0xb7, 0x6d, 0x46, 0x50, 0x16, 0x89, 0x15, } } /*ae2ee509-1b34-41c0-acb7-6d4650168915*/, "Windows 7 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0x1cb6d605, 0x11b3, 0x4e14, { 0xbb, 0x30, 0xda, 0x91, 0xc8, 0xe3, 0x98, 0x3a, } } /*1cb6d605-11b3-4e14-bb30-da91c8e3983a*/, "Windows 7 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0xb92e9980, 0xb9d5, 0x4821, { 0x9c, 0x94, 0x14, 0x0f, 0x63, 0x2f, 0x63, 0x12, } } /*b92e9980-b9d5-4821-9c94-140f632f6312*/, "Windows 7 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0x54a09a0d, 0xd57b, 0x4c10, { 0x8b, 0x69, 0xa8, 0x42, 0xd6, 0x59, 0x0a, 0xd5, } } /*54a09a0d-d57b-4c10-8b69-a842d6590ad5*/, "Windows 7 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
-
-
- // Windows Vista
-
- { { 0xcfd8ff08, 0xc0d7, 0x452b, { 0x9f, 0x60, 0xef, 0x5c, 0x70, 0xc3, 0x20, 0x94, } } /*cfd8ff08-c0d7-452b-9f60-ef5c70c32094*/, "Windows Vista Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
- { { 0xd4f54950, 0x26f2, 0x4fb4, { 0xba, 0x21, 0xff, 0xab, 0x16, 0xaf, 0xca, 0xde, } } /*d4f54950-26f2-4fb4-ba21-ffab16afcade*/, "Windows Vista Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
- { { 0x4f3d1606, 0x3fea, 0x4c01, { 0xbe, 0x3c, 0x8d, 0x67, 0x1c, 0x40, 0x1e, 0x3b, } } /*4f3d1606-3fea-4c01-be3c-8d671c401e3b*/, "Windows Vista Business", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
- { { 0x2c682dc2, 0x8b68, 0x4f63, { 0xa1, 0x65, 0xae, 0x29, 0x1d, 0x4c, 0xf1, 0x38, } } /*2c682dc2-8b68-4f63-a165-ae291d4cf138*/, "Windows Vista Business N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
-
-
- // Windows Embedded
-
- { { 0xaa6dd3aa, 0xc2b4, 0x40e2, { 0xa5, 0x44, 0xa6, 0xbb, 0xb3, 0xf5, 0xc3, 0x95, } } /*aa6dd3aa-c2b4-40e2-a544-a6bbb3f5c395*/, "Windows ThinPC", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0xdb537896, 0x376f, 0x48ae, { 0xa4, 0x92, 0x53, 0xd0, 0x54, 0x77, 0x73, 0xd0, } } /*db537896-376f-48ae-a492-53d0547773d0*/, "Windows Embedded POSReady 7", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0x0ab82d54, 0x47f4, 0x4acb, { 0x81, 0x8c, 0xcc, 0x5b, 0xf0, 0xec, 0xb6, 0x49, } } /*0ab82d54-47f4-4acb-818c-cc5bf0ecb649*/, "Windows Embedded Industry 8.1", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xcd4e2d9f, 0x5059, 0x4a50, { 0xa9, 0x2d, 0x05, 0xd5, 0xbb, 0x12, 0x67, 0xc7, } } /*cd4e2d9f-5059-4a50-a92d-05d5bb1267c7*/, "Windows Embedded Industry E 8.1", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xf7e88590, 0xdfc7, 0x4c78, { 0xbc, 0xcb, 0x6f, 0x38, 0x65, 0xb9, 0x9d, 0x1a, } } /*f7e88590-dfc7-4c78-bccb-6f3865b99d1a*/, "Windows Embedded Industry A 8.1", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
-
- // Office 2010
-
- { { 0x8ce7e872, 0x188c, 0x4b98, { 0x9d, 0x90, 0xf8, 0xf9, 0x0b, 0x7a, 0xad, 0x02, } } /*8ce7e872-188c-4b98-9d90-f8f90b7aad02*/, "Office Access 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xcee5d470, 0x6e3b, 0x4fcc, { 0x8c, 0x2b, 0xd1, 0x74, 0x28, 0x56, 0x8a, 0x9f, } } /*cee5d470-6e3b-4fcc-8c2b-d17428568a9f*/, "Office Excel 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x8947d0b8, 0xc33b, 0x43e1, { 0x8c, 0x56, 0x9b, 0x67, 0x4c, 0x05, 0x28, 0x32, } } /*8947d0b8-c33b-43e1-8c56-9b674c052832*/, "Office Groove 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xca6b6639, 0x4ad6, 0x40ae, { 0xa5, 0x75, 0x14, 0xde, 0xe0, 0x7f, 0x64, 0x30, } } /*ca6b6639-4ad6-40ae-a575-14dee07f6430*/, "Office InfoPath 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x09ed9640, 0xf020, 0x400a, { 0xac, 0xd8, 0xd7, 0xd8, 0x67, 0xdf, 0xd9, 0xc2, } } /*09ed9640-f020-400a-acd8-d7d867dfd9c2*/, "Office Mondo 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xef3d4e49, 0xa53d, 0x4d81, { 0xa2, 0xb1, 0x2c, 0xa6, 0xc2, 0x55, 0x6b, 0x2c, } } /*ef3d4e49-a53d-4d81-a2b1-2ca6c2556b2c*/, "Office Mondo 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xab586f5c, 0x5256, 0x4632, { 0x96, 0x2f, 0xfe, 0xfd, 0x8b, 0x49, 0xe6, 0xf4, } } /*ab586f5c-5256-4632-962f-fefd8b49e6f4*/, "Office OneNote 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xecb7c192, 0x73ab, 0x4ded, { 0xac, 0xf4, 0x23, 0x99, 0xb0, 0x95, 0xd0, 0xcc, } } /*ecb7c192-73ab-4ded-acf4-2399b095d0cc*/, "Office OutLook 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x45593b1d, 0xdfb1, 0x4e91, { 0xbb, 0xfb, 0x2d, 0x5d, 0x0c, 0xe2, 0x22, 0x7a, } } /*45593b1d-dfb1-4e91-bbfb-2d5d0ce2227a*/, "Office PowerPoint 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xdf133ff7, 0xbf14, 0x4f95, { 0xaf, 0xe3, 0x7b, 0x48, 0xe7, 0xe3, 0x31, 0xef, } } /*df133ff7-bf14-4f95-afe3-7b48e7e331ef*/, "Office Project Pro 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x5dc7bf61, 0x5ec9, 0x4996, { 0x9c, 0xcb, 0xdf, 0x80, 0x6a, 0x2d, 0x0e, 0xfe, } } /*5dc7bf61-5ec9-4996-9ccb-df806a2d0efe*/, "Office Project Standard 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xb50c4f75, 0x599b, 0x43e8, { 0x8d, 0xcd, 0x10, 0x81, 0xa7, 0x96, 0x72, 0x41, } } /*b50c4f75-599b-43e8-8dcd-1081a7967241*/, "Office Publisher 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x92236105, 0xbb67, 0x494f, { 0x94, 0xc7, 0x7f, 0x7a, 0x60, 0x79, 0x29, 0xbd, } } /*92236105-bb67-494f-94c7-7f7a607929bd*/, "Office Visio Premium 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xe558389c, 0x83c3, 0x4b29, { 0xad, 0xfe, 0x5e, 0x4d, 0x7f, 0x46, 0xc3, 0x58, } } /*e558389c-83c3-4b29-adfe-5e4d7f46c358*/, "Office Visio Pro 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x9ed833ff, 0x4f92, 0x4f36, { 0xb3, 0x70, 0x86, 0x83, 0xa4, 0xf1, 0x32, 0x75, } } /*9ed833ff-4f92-4f36-b370-8683a4f13275*/, "Office Visio Standard 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x2d0882e7, 0xa4e7, 0x423b, { 0x8c, 0xcc, 0x70, 0xd9, 0x1e, 0x01, 0x58, 0xb1, } } /*2d0882e7-a4e7-423b-8ccc-70d91e0158b1*/, "Office Word 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x6f327760, 0x8c5c, 0x417c, { 0x9b, 0x61, 0x83, 0x6a, 0x98, 0x28, 0x7e, 0x0c, } } /*6f327760-8c5c-417c-9b61-836a98287e0c*/, "Office Professional Plus 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x9da2a678, 0xfb6b, 0x4e67, { 0xab, 0x84, 0x60, 0xdd, 0x6a, 0x9c, 0x81, 0x9a, } } /*9da2a678-fb6b-4e67-ab84-60dd6a9c819a*/, "Office Standard 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xea509e87, 0x07a1, 0x4a45, { 0x9e, 0xdc, 0xeb, 0xa5, 0xa3, 0x9f, 0x36, 0xaf, } } /*ea509e87-07a1-4a45-9edc-eba5a39f36af*/, "Office Small Business Basics 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
-
- // Office 2013
-
- { { 0x6ee7622c, 0x18d8, 0x4005, { 0x9f, 0xb7, 0x92, 0xdb, 0x64, 0x4a, 0x27, 0x9b, } } /*6ee7622c-18d8-4005-9fb7-92db644a279b*/, "Office Access 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xf7461d52, 0x7c2b, 0x43b2, { 0x87, 0x44, 0xea, 0x95, 0x8e, 0x0b, 0xd0, 0x9a, } } /*f7461d52-7c2b-43b2-8744-ea958e0bd09a*/, "Office Excel 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xa30b8040, 0xd68a, 0x423f, { 0xb0, 0xb5, 0x9c, 0xe2, 0x92, 0xea, 0x5a, 0x8f, } } /*a30b8040-d68a-423f-b0b5-9ce292ea5a8f*/, "Office InfoPath 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x1b9f11e3, 0xc85c, 0x4e1b, { 0xbb, 0x29, 0x87, 0x9a, 0xd2, 0xc9, 0x09, 0xe3, } } /*1b9f11e3-c85c-4e1b-bb29-879ad2c909e3*/, "Office Lync 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xdc981c6b, 0xfc8e, 0x420f, { 0xaa, 0x43, 0xf8, 0xf3, 0x3e, 0x5c, 0x09, 0x23, } } /*dc981c6b-fc8e-420f-aa43-f8f33e5c0923*/, "Office Mondo 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xefe1f3e6, 0xaea2, 0x4144, { 0xa2, 0x08, 0x32, 0xaa, 0x87, 0x2b, 0x65, 0x45, } } /*efe1f3e6-aea2-4144-a208-32aa872b6545*/, "Office OneNote 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x771c3afa, 0x50c5, 0x443f, { 0xb1, 0x51, 0xff, 0x25, 0x46, 0xd8, 0x63, 0xa0, } } /*771c3afa-50c5-443f-b151-ff2546d863a0*/, "Office OutLook 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x8c762649, 0x97d1, 0x4953, { 0xad, 0x27, 0xb7, 0xe2, 0xc2, 0x5b, 0x97, 0x2e, } } /*8c762649-97d1-4953-ad27-b7e2c25b972e*/, "Office PowerPoint 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x4a5d124a, 0xe620, 0x44ba, { 0xb6, 0xff, 0x65, 0x89, 0x61, 0xb3, 0x3b, 0x9a, } } /*4a5d124a-e620-44ba-b6ff-658961b33b9a*/, "Office Project Pro 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x427a28d1, 0xd17c, 0x4abf, { 0xb7, 0x17, 0x32, 0xc7, 0x80, 0xba, 0x6f, 0x07, } } /*427a28d1-d17c-4abf-b717-32c780ba6f07*/, "Office Project Standard 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x00c79ff1, 0x6850, 0x443d, { 0xbf, 0x61, 0x71, 0xcd, 0xe0, 0xde, 0x30, 0x5f, } } /*00c79ff1-6850-443d-bf61-71cde0de305f*/, "Office Publisher 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xac4efaf0, 0xf81f, 0x4f61, { 0xbd, 0xf7, 0xea, 0x32, 0xb0, 0x2a, 0xb1, 0x17, } } /*ac4efaf0-f81f-4f61-bdf7-ea32b02ab117*/, "Office Visio Standard 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xe13ac10e, 0x75d0, 0x4aff, { 0xa0, 0xcd, 0x76, 0x49, 0x82, 0xcf, 0x54, 0x1c, } } /*e13ac10e-75d0-4aff-a0cd-764982cf541c*/, "Office Visio Pro 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xd9f5b1c6, 0x5386, 0x495a, { 0x88, 0xf9, 0x9a, 0xd6, 0xb4, 0x1a, 0xc9, 0xb3, } } /*d9f5b1c6-5386-495a-88f9-9ad6b41ac9b3*/, "Office Word 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xb322da9c, 0xa2e2, 0x4058, { 0x9e, 0x4e, 0xf5, 0x9a, 0x69, 0x70, 0xbd, 0x69, } } /*b322da9c-a2e2-4058-9e4e-f59a6970bd69*/, "Office Professional Plus 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xb13afb38, 0xcd79, 0x4ae5, { 0x9f, 0x7f, 0xee, 0xd0, 0x58, 0xd7, 0x50, 0xca, } } /*b13afb38-cd79-4ae5-9f7f-eed058d750ca*/, "Office Standard 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
-
- // Office 2016
-
- { { 0xd450596f, 0x894d, 0x49e0, { 0x96, 0x6a, 0xfd, 0x39, 0xed, 0x4c, 0x4c, 0x64, } } /*d450596f-894d-49e0-966a-fd39ed4c4c64*/, "Office Professional Plus 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x4f414197, 0x0fc2, 0x4c01, { 0xb6, 0x8a, 0x86, 0xcb, 0xb9, 0xac, 0x25, 0x4c, } } /*4f414197-0fc2-4c01-b68a-86cbb9ac254c*/, "Office Project Pro 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x6bf301c1, 0xb94a, 0x43e9, { 0xba, 0x31, 0xd4, 0x94, 0x59, 0x8c, 0x47, 0xfb, } } /*6bf301c1-b94a-43e9-ba31-d494598c47fb*/, "Office Visio Pro 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x041a06cb, 0xc5b8, 0x4772, { 0x80, 0x9f, 0x41, 0x6d, 0x03, 0xd1, 0x66, 0x54, } } /*041a06cb-c5b8-4772-809f-416d03d16654*/, "Office Publisher 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x67c0fc0c, 0xdeba, 0x401b, { 0xbf, 0x8b, 0x9c, 0x8a, 0xd8, 0x39, 0x58, 0x04, } } /*67c0fc0c-deba-401b-bf8b-9c8ad8395804*/, "Office Access 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x83e04ee1, 0xfa8d, 0x436d, { 0x89, 0x94, 0xd3, 0x1a, 0x86, 0x2c, 0xab, 0x77, } } /*83e04ee1-fa8d-436d-8994-d31a862cab77*/, "Office Skype for Business 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x9caabccb, 0x61b1, 0x4b4b, { 0x8b, 0xec, 0xd1, 0x0a, 0x3c, 0x3a, 0xc2, 0xce, } } /*9caabccb-61b1-4b4b-8bec-d10a3c3ac2ce*/, "Office Mondo 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xaa2a7821, 0x1827, 0x4c2c, { 0x8f, 0x1d, 0x45, 0x13, 0xa3, 0x4d, 0xda, 0x97, } } /*aa2a7821-1827-4c2c-8f1d-4513a34dda97*/, "Office Visio Standard 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xbb11badf, 0xd8aa, 0x470e, { 0x93, 0x11, 0x20, 0xea, 0xf8, 0x0f, 0xe5, 0xcc, } } /*bb11badf-d8aa-470e-9311-20eaf80fe5cc*/, "Office Word 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xc3e65d36, 0x141f, 0x4d2f, { 0xa3, 0x03, 0xa8, 0x42, 0xee, 0x75, 0x6a, 0x29, } } /*c3e65d36-141f-4d2f-a303-a842ee756a29*/, "Office Excel 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xd70b1bba, 0xb893, 0x4544, { 0x96, 0xe2, 0xb7, 0xa3, 0x18, 0x09, 0x1c, 0x33, } } /*d70b1bba-b893-4544-96e2-b7a318091c33*/, "Office Powerpoint 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xd8cace59, 0x33d2, 0x4ac7, { 0x9b, 0x1b, 0x9b, 0x72, 0x33, 0x9c, 0x51, 0xc8, } } /*d8cace59-33d2-4ac7-9b1b-9b72339c51c8*/, "Office OneNote 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xda7ddabc, 0x3fbe, 0x4447, { 0x9e, 0x01, 0x6a, 0xb7, 0x44, 0x0b, 0x4c, 0xd4, } } /*da7ddabc-3fbe-4447-9e01-6ab7440b4cd4*/, "Office Project Standard 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xdedfa23d, 0x6ed1, 0x45a6, { 0x85, 0xdc, 0x63, 0xca, 0xe0, 0x54, 0x6d, 0xe6, } } /*dedfa23d-6ed1-45a6-85dc-63cae0546de6*/, "Office Standard 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xe914ea6e, 0xa5fa, 0x4439, { 0xa3, 0x94, 0xa9, 0xbb, 0x32, 0x93, 0xca, 0x09, } } /*e914ea6e-a5fa-4439-a394-a9bb3293ca09*/, "Office Mondo R 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xec9d9265, 0x9d1e, 0x4ed0, { 0x83, 0x8a, 0xcd, 0xc2, 0x0f, 0x25, 0x51, 0xa1, } } /*ec9d9265-9d1e-4ed0-838a-cdc20f2551a1*/, "Office Outlook 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
-
- // End marker (necessity should be removed when time permits)
-
- { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
-};
-
-
-// necessary because other .c files cannot access _countof()
-__pure ProdListIndex_t getExtendedProductListSize(void)
-{
- return _countof(ExtendedProductList) - 1;
-}
-
-__pure ProdListIndex_t getAppListSize(void)
-{
- return _countof(AppList);
-}
-
-#endif
-
-#ifndef NO_RANDOM_EPID
-// HostType and OSBuild
-static const struct KMSHostOS { uint16_t Type; uint16_t Build; } HostOS[] =
-{
- { 55041, 6002 }, // Windows Server 2008 SP2
- { 55041, 7601 }, // Windows Server 2008 R2 SP1
- { 5426, 9200 }, // Windows Server 2012
- { 6401, 9600 }, // Windows Server 2012 R2
- { 3612, 10240}, // Windows Server 2016
-};
-
-// GroupID and PIDRange
-static const struct PKEYCONFIG { uint16_t GroupID; uint32_t RangeMin; uint32_t RangeMax; } pkeyconfig[] = {
- { 206, 152000000, 191999999 }, // Windows Server 2012 KMS Host pkeyconfig
- { 206, 271000000, 310999999 }, // Windows Server 2012 R2 KMS Host pkeyconfig
- { 96, 199000000, 217999999 }, // Office2010 KMS Host pkeyconfig
- { 206, 234000000, 255999999 }, // Office2013 KMS Host pkeyconfig
-};
-
-// Valid language identifiers to be used in the ePID
-static const uint16_t LcidList[] = {
- 1078, 1052, 1025, 2049, 3073, 4097, 5121, 6145, 7169, 8193, 9217, 10241, 11265, 12289, 13313, 14337, 15361, 16385,
- 1067, 1068, 2092, 1069, 1059, 1093, 5146, 1026, 1027, 1028, 2052, 3076, 4100, 5124, 1050, 4122, 1029, 1030, 1125, 1043, 2067,
- 1033, 2057, 3081, 4105, 5129, 6153, 7177, 8201, 9225, 10249, 11273, 12297, 13321, 1061, 1080, 1065, 1035, 1036, 2060,
- 3084, 4108, 5132, 6156, 1079, 1110, 1031, 2055, 3079, 4103, 5127, 1032, 1095, 1037, 1081, 1038, 1039, 1057, 1040, 2064, 1041, 1099,
- 1087, 1111, 1042, 1088, 1062, 1063, 1071, 1086, 2110, 1100, 1082, 1153, 1102, 1104, 1044, 2068, 1045, 1046, 2070,
- 1094, 1131, 2155, 3179, 1048, 1049, 9275, 4155, 5179, 3131, 1083, 2107, 8251, 6203, 7227, 1103, 2074, 6170, 3098,
- 7194, 1051, 1060, 1034, 2058, 3082, 4106, 5130, 6154, 7178, 8202, 9226, 10250, 11274, 12298, 13322, 14346, 15370, 16394,
- 17418, 18442, 19466, 20490, 1089, 1053, 2077, 1114, 1097, 1092, 1098, 1054, 1074, 1058, 1056, 1091, 2115, 1066, 1106, 1076, 1077
-};
-
-
-#ifdef _PEDANTIC
-uint16_t IsValidLcid(const uint16_t Lcid)
-{
- uint16_t i;
-
- for (i = 0; i < _countof(LcidList); i++)
- {
- if (Lcid == LcidList[i]) return Lcid;
- }
-
- return 0;
-}
-#endif // _PEDANTIC
-#endif // NO_RANDOM_EPID
-
-
-// Unix time is seconds from 1970-01-01. Should be 64 bits to avoid Year 2035 overflow bug.
-// FILETIME is 100 nanoseconds from 1601-01-01. Must be 64 bits.
-void getUnixTimeAsFileTime(FILETIME *const ts)
-{
- int64_t unixtime = (int64_t)time(NULL);
- int64_t *filetime = (int64_t*)ts;
-
- *filetime = LE64( (unixtime + 11644473600LL) * 10000000LL );
-}
-
-__pure int64_t fileTimeToUnixTime(const FILETIME *const ts)
-{
- return LE64( *((const int64_t *const)ts) ) / 10000000LL - 11644473600LL;
-}
-
-
-/*
- * Get's a product name with a GUID in host-endian order.
- * List can be any list defined above.
- */
-const char* getProductNameHE(const GUID *const guid, const KmsIdList *const List, ProdListIndex_t *const i)
-{
- for (*i = 0; List[*i].name != NULL; (*i)++)
- {
- if (IsEqualGUID(guid, &List[*i].guid))
- return List[*i].name;
- }
-
- return "Unknown";
-}
-
-
-/*
- * same as getProductnameHE except GUID is in little-endian (network) order
- */
-const char* getProductNameLE(const GUID *const guid, const KmsIdList *const List, ProdListIndex_t *const i)
-{
- #if __BYTE_ORDER != __LITTLE_ENDIAN
- GUID HeGUID;
- LEGUID(&HeGUID, guid);
- return getProductNameHE(&HeGUID, List, i);
- #else
- return getProductNameHE(guid, List, i);
- #endif
-}
-
-
-#ifndef NO_RANDOM_EPID
-// formats an int with a fixed number of digits with leading zeros (helper for ePID generation)
-static char* itoc(char *const c, const int i, uint_fast8_t digits)
-{
- char formatString[8];
- if (digits > 9) digits = 0;
- strcpy(formatString,"%");
-
- if (digits)
- {
- formatString[1] = '0';
- formatString[2] = digits | 0x30;
- formatString[3] = 0;
- }
-
- strcat(formatString, "u");
- sprintf(c, formatString, i);
- return c;
-}
-
-static int getRandomServerType()
-{
-# ifndef USE_MSRPC
- if (!UseRpcBTFN)
-# endif // USE_MSRPC
- {
- // This isn't possible at all, e.g. KMS host on XP
- return rand() % (int)_countof(HostOS);
- }
-# ifndef USE_MSRPC
- else
- {
- // return 9200/9600/10240 if NDR64 is in use, otherwise 6002/7601
- if (UseRpcNDR64) return (rand() % 3) + 2;
- return (rand() % 2);
- }
-# endif // USE_MSRPC
-}
-
-
-/*
- * Generates a random ePID
- */
-static void generateRandomPid(const int index, char *const szPid, int serverType, int16_t lang)
-{
- int clientApp;
- char numberBuffer[12];
-
- if (serverType < 0 || serverType >= (int)_countof(HostOS))
- {
- serverType = getRandomServerType();
- }
-
- strcpy(szPid, itoc(numberBuffer, HostOS[serverType].Type, 5));
- strcat(szPid, "-");
-
- if (index == 2)
- clientApp = 3;
- else if (index == 1)
- clientApp = 2;
- else
- clientApp = serverType == 3 /*change if HostOS changes*/ ? 1 : 0;
-
- strcat(szPid, itoc(numberBuffer, pkeyconfig[clientApp].GroupID, 5));
- strcat(szPid, "-");
-
- int keyId = (rand32() % (pkeyconfig[clientApp].RangeMax - pkeyconfig[clientApp].RangeMin)) + pkeyconfig[clientApp].RangeMin;
- strcat(szPid, itoc(numberBuffer, keyId / 1000000, 3));
- strcat(szPid, "-");
- strcat(szPid, itoc(numberBuffer, keyId % 1000000, 6));
- strcat(szPid, "-03-");
-
- if (lang < 0) lang = LcidList[rand() % _countof(LcidList)];
- strcat(szPid, itoc(numberBuffer, lang, 0));
- strcat(szPid, "-");
-
- strcat(szPid, itoc(numberBuffer, HostOS[serverType].Build, 0));
- strcat(szPid, ".0000-");
-
-# define minTime ((time_t)1436958000) // Release Date Windows 10 RTM Escrow
-
- time_t maxTime, kmsTime;
- time(&maxTime);
-
- if (maxTime < minTime) // Just in case the system time is < 07/15/2015 1:00 pm
- maxTime = (time_t)BUILD_TIME;
-
- kmsTime = (rand32() % (maxTime - minTime)) + minTime;
-# undef minTime
-
- struct tm *pidTime;
- pidTime = gmtime(&kmsTime);
-
- strcat(szPid, itoc(numberBuffer, pidTime->tm_yday, 3));
- strcat(szPid, itoc(numberBuffer, pidTime->tm_year + 1900, 4));
-}
-
-
-/*
- * Generates random ePIDs and stores them if not already read from ini file.
- * For use with randomization level 1
- */
-void randomPidInit()
-{
- ProdListIndex_t i;
-
- int serverType = getRandomServerType();
- int16_t lang = Lcid ? Lcid : LcidList[rand() % _countof(LcidList)];
-
- for (i = 0; i < _countof(AppList) - 1; i++)
- {
- if (KmsResponseParameters[i].Epid) continue;
-
- char Epid[PID_BUFFER_SIZE];
-
- generateRandomPid(i, Epid, serverType, lang);
- KmsResponseParameters[i].Epid = (const char*)vlmcsd_malloc(strlen(Epid) + 1);
-
- strcpy((char*)KmsResponseParameters[i].Epid, Epid);
-
- #ifndef NO_LOG
- KmsResponseParameters[i].EpidSource = "randomized at program start";
- #endif // NO_LOG
- }
-}
-
-#endif // NO_RANDOM_EPID
-
-
-#ifndef NO_LOG
-/*
- * Logs a Request
- */
-static void logRequest(const REQUEST *const baseRequest)
-{
- const char *productName;
- char clientname[64];
- ProdListIndex_t index;
-
- #ifndef NO_EXTENDED_PRODUCT_LIST
- productName = getProductNameLE(&baseRequest->ActID, ExtendedProductList, &index);
- if (++index >= (int)_countof(ExtendedProductList))
- #endif // NO_EXTENDED_PRODUCT_LIST
- {
- #ifndef NO_BASIC_PRODUCT_LIST
- productName = getProductNameLE(&baseRequest->KMSID, ProductList, &index);
- if (++index >= (int)_countof(ProductList))
- #endif // NO_BASIC_PRODUCT_LIST
- {
- productName = getProductNameLE(&baseRequest->AppID, AppList, &index);
- }
- }
-
- #ifndef NO_VERBOSE_LOG
- if (logverbose)
- {
- logger("<<< Incoming KMS request\n");
- logRequestVerbose(baseRequest, &logger);
- }
- else
- {
- #endif // NO_VERBOSE_LOG
- 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);
- #ifndef NO_VERBOSE_LOG
- }
- #endif // NO_VERBOSE_LOG
-}
-#endif // NO_LOG
-
-
-/*
- * Converts a utf-8 ePID string to UCS-2 and writes it to a RESPONSE struct
- */
-static void getEpidFromString(RESPONSE *const Response, const char *const pid)
-{
- size_t length = utf8_to_ucs2(Response->KmsPID, pid, PID_BUFFER_SIZE, PID_BUFFER_SIZE * 3);
- Response->PIDSize = LE32(((unsigned int )length + 1) << 1);
-}
-
-
-/*
- * get ePID from appropriate source
- */
-static void getEpid(RESPONSE *const baseResponse, const char** EpidSource, const ProdListIndex_t index, BYTE *const HwId)
-{
- const char* pid;
- if (KmsResponseParameters[index].Epid == NULL)
- {
- #ifndef NO_RANDOM_EPID
- if (RandomizationLevel == 2)
- {
- char szPid[PID_BUFFER_SIZE];
- generateRandomPid(index, szPid, -1, Lcid ? Lcid : -1);
- pid = szPid;
-
- #ifndef NO_LOG
- *EpidSource = "randomized on every request";
- #endif // NO_LOG
- }
- else
- #endif // NO_RANDOM_EPID
- {
- pid = AppList[index].pid;
- #ifndef NO_LOG
- *EpidSource = "vlmcsd default";
- #endif // NO_LOG
- }
- }
- else
- {
- pid = KmsResponseParameters[index].Epid;
-
- if (HwId && KmsResponseParameters[index].HwId != NULL)
- memcpy(HwId, KmsResponseParameters[index].HwId, sizeof(((RESPONSE_V6 *)0)->HwId));
-
- #ifndef NO_LOG
- *EpidSource = KmsResponseParameters[index].EpidSource;
- #endif // NO_LOG
- }
- getEpidFromString(baseResponse, pid);
-}
-
-
-#if !defined(NO_LOG) && defined(_PEDANTIC)
-static BOOL CheckVersion4Uuid(const GUID *const guid, const char *const szGuidName)
-{
- if (LE16(guid->Data3) >> 12 != 4 || guid->Data4[0] >> 6 != 2)
- {
- logger("Warning: %s does not conform to version 4 UUID according to RFC 4122\n", szGuidName);
- return FALSE;
- }
- return TRUE;
-}
-
-
-static void CheckRequest(const REQUEST *const Request)
-{
- CheckVersion4Uuid(&Request->CMID, "Client machine ID");
- CheckVersion4Uuid(&Request->AppID, "Application ID");
- CheckVersion4Uuid(&Request->KMSID, "Server SKU ID");
- CheckVersion4Uuid(&Request->ActID, "Client SKU ID");
-
- if (LE32(Request->IsClientVM) > 1)
- logger("Warning: Virtual Machine field in request must be 0 or 1 but is %u\n", LE32(Request->IsClientVM));
-
- if (LE32(Request->LicenseStatus) > 6 )
- logger("Warning: License status must be between 0 and 6 but is %u\n", LE32(Request->LicenseStatus));
-}
-#endif // !defined(NO_LOG) && defined(_PEDANTIC)
-
-
-#ifndef NO_LOG
-/*
- * Logs the Response
- */
-static void logResponse(const RESPONSE *const 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);
-
- #ifndef NO_VERBOSE_LOG
- if (!logverbose)
- {
- #endif // NO_VERBOSE_LOG
- logger("Sending ePID (%s): %s\n", EpidSource, utf8pid);
- #ifndef NO_VERBOSE_LOG
- }
- else
- {
- logger(">>> Sending response, ePID source = %s\n", EpidSource);
- logResponseVerbose(utf8pid, hwId, baseResponse, &logger);
- }
- #endif // NO_VERBOSE_LOG
-
-}
-#endif
-
-
-/*
- * Creates the unencrypted base response
- */
-static BOOL __stdcall CreateResponseBaseCallback(const REQUEST *const baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr)
-{
- const char* EpidSource;
- #ifndef NO_LOG
- logRequest(baseRequest);
- #ifdef _PEDANTIC
- CheckRequest(baseRequest);
- #endif // _PEDANTIC
- #endif // NO_LOG
-
- ProdListIndex_t index;
-
- getProductNameLE(&baseRequest->AppID, AppList, &index);
-
- if (index >= _countof(AppList) - 1) index = 0; //default to Windows
-
- getEpid(baseResponse, &EpidSource, index, hwId);
-
- baseResponse->Version = baseRequest->Version;
-
- memcpy(&baseResponse->CMID, &baseRequest->CMID, sizeof(GUID));
- memcpy(&baseResponse->ClientTime, &baseRequest->ClientTime, sizeof(FILETIME));
-
- baseResponse->Count = LE32(LE32(baseRequest->N_Policy) << 1);
- baseResponse->VLActivationInterval = LE32(VLActivationInterval);
- baseResponse->VLRenewalInterval = LE32(VLRenewalInterval);
-
- #ifndef NO_LOG
- logResponse(baseResponse, hwId, EpidSource);
- #endif // NO_LOG
-
- return !0;
-}
-
-RequestCallback_t CreateResponseBase = &CreateResponseBaseCallback;
-
-////TODO: Move to helpers.c
-void get16RandomBytes(void* ptr)
-{
- int i;
- for (i = 0; i < 4; i++) ((DWORD*)ptr)[i] = rand32();
-}
-
-
-/*
- * Creates v4 response
- */
-size_t CreateResponseV4(REQUEST_V4 *const request_v4, BYTE *const responseBuffer, const char* const ipstr)
-{
- RESPONSE_V4* Response = (RESPONSE_V4*)responseBuffer;
-
- if ( !CreateResponseBase(&request_v4->RequestBase, &Response->ResponseBase, NULL, ipstr) ) return 0;
-
- DWORD pidSize = LE32(Response->ResponseBase.PIDSize);
- BYTE* postEpidPtr = responseBuffer + V4_PRE_EPID_SIZE + pidSize;
- memmove(postEpidPtr, &Response->ResponseBase.CMID, V4_POST_EPID_SIZE);
-
- size_t encryptSize = V4_PRE_EPID_SIZE + V4_POST_EPID_SIZE + pidSize;
- AesCmacV4(responseBuffer, encryptSize, responseBuffer + encryptSize);
-
- return encryptSize + sizeof(Response->MAC);
-}
-
-/*
-// Workaround for buggy GCC 4.2/4.3
-#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 4)
-__attribute__((noinline))
-#endif
-__pure static uint64_t TimestampInterval(void *ts)
-{
- return ( GET_UA64LE(ts) / TIME_C1 ) * TIME_C2 + TIME_C3;
-}*/
-
-
-/*
- * Creates the HMAC for v6
- */
-static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptSize, int_fast8_t tolerance)
-{
- BYTE hash[32];
-# define halfHashSize (sizeof(hash) >> 1)
- uint64_t timeSlot;
- BYTE *responseEnd = encrypt_start + encryptSize;
-
- // This is the time from the response
- 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.
- // When generating a response tolerance must be 0.
- // If verifying the hash, try tolerance -1, 0 and +1. One of them must match.
-
- timeSlot = LE64( (GET_UA64LE(ft) / TIME_C1 * TIME_C2 + TIME_C3) + (tolerance * TIME_C1) );
-
- // The time slot is hashed with SHA256 so it is not so obvious that it is time
- Sha256((BYTE*) &timeSlot, sizeof(timeSlot), hash);
-
- // The last 16 bytes of the hashed time slot are the actual HMAC key
- if (!Sha256Hmac
- (
- hash + halfHashSize, // Use last 16 bytes of SHA256 as HMAC key
- encrypt_start, // hash only the encrypted part of the v6 response
- encryptSize - sizeof(((RESPONSE_V6*)0)->HMAC), // encryptSize minus the HMAC itself
- hash // use same buffer for resulting hash where the key came from
- ))
- {
- return FALSE;
- }
-
- memcpy(responseEnd - sizeof(((RESPONSE_V6*)0)->HMAC), hash + halfHashSize, halfHashSize);
- return TRUE;
-# undef halfHashSize
-}
-
-
-/*
- * Creates v5 or v6 response
- */
-size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuffer, const char* const ipstr)
-{
- // The response will be created in a fixed sized struct to
- // avoid unaligned access macros and packed structs on RISC systems
- // which largely increase code size.
- //
- // 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;
-
- #ifdef _DEBUG
- RESPONSE_V6_DEBUG* xxx = (RESPONSE_V6_DEBUG*)responseBuffer;
- #endif
-
- static const BYTE DefaultHwid[8] = { HWID };
- int_fast8_t v6 = LE16(request_v6->MajorVer) > 5;
- AesCtx aesCtx;
-
- AesInitKey(&aesCtx, v6 ? AesKeyV6 : AesKeyV5, v6, AES_KEY_BYTES);
- 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);
-
- if (v6) // V6 specific stuff
- {
- // In v6 a random IV is generated
- Response->Version = request_v6->Version;
- get16RandomBytes(Response->IV);
-
- // pre-fill with default HwId (not required for v5)
- 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));
- }
- 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);
- }
-
- // Xor Random bytes with decrypted request IV
- XorBlock(request_v6->IV, Response->RandomXoredIVs);
-
- // Get the base response
- if ( !CreateResponseBase(&request_v6->RequestBase, baseResponse, Response->HwId, ipstr) ) return 0;
-
- // Convert the fixed sized struct into variable sized
- DWORD pidSize = LE32(baseResponse->PIDSize);
- BYTE* postEpidPtr = responseBuffer + V6_PRE_EPID_SIZE + pidSize;
- size_t post_epid_size = v6 ? V6_POST_EPID_SIZE : V5_POST_EPID_SIZE;
-
- memmove(postEpidPtr, &baseResponse->CMID, post_epid_size);
-
- // number of bytes to encrypt
- size_t encryptSize =
- V6_PRE_EPID_SIZE
- - sizeof(Response->Version)
- + pidSize
- + post_epid_size;
-
- //AesDecryptBlock(&aesCtx, Response->IV);
- if (v6 && !CreateV6Hmac(Response->IV, encryptSize, 0)) return 0;
-
- // Padding auto handled by encryption func
- AesEncryptCbc(&aesCtx, NULL, Response->IV, &encryptSize);
-
- return encryptSize + sizeof(Response->Version);
-}
-
-
-// Create Hashed KMS Client Request Data for KMS Protocol Version 4
-BYTE *CreateRequestV4(size_t *size, const REQUEST* requestBase)
-{
- *size = sizeof(REQUEST_V4);
-
- // Build a proper KMS client request data
- BYTE *request = (BYTE *)vlmcsd_malloc(sizeof(REQUEST_V4));
-
- // Temporary Pointer for access to REQUEST_V4 structure
- REQUEST_V4 *request_v4 = (REQUEST_V4 *)request;
-
- // Set KMS Client Request Base
- memcpy(&request_v4->RequestBase, requestBase, sizeof(REQUEST));
-
- // Generate Hash Signature
- AesCmacV4(request, sizeof(REQUEST), request_v4->MAC);
-
- // Return Request Data
- return request;
-}
-
-
-// Create Encrypted KMS Client Request Data for KMS Protocol Version 6
-BYTE* CreateRequestV6(size_t *size, const REQUEST* requestBase)
-{
- *size = sizeof(REQUEST_V6);
-
- // Temporary Pointer for access to REQUEST_V5 structure
- REQUEST_V6 *request = (REQUEST_V6 *)vlmcsd_malloc(sizeof(REQUEST_V6));
-
- // KMS Protocol Version
- request->Version = requestBase->Version;
-
- // Initialize the IV
- get16RandomBytes(request->IV);
-
- // Set KMS Client Request Base
- memcpy(&request->RequestBase, requestBase, sizeof(REQUEST));
-
- // 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);
-
- // Return Proper Request Data
- return (BYTE*)request;
-}
-
-
-/*
- * Checks whether Length of ePID is valid
- */
-static uint8_t checkPidLength(const RESPONSE *const responseBase)
-{
- unsigned int i;
-
- if (LE32(responseBase->PIDSize) > (PID_BUFFER_SIZE << 1)) return FALSE;
- if (responseBase->KmsPID[(LE32(responseBase->PIDSize) >> 1) - 1]) return FALSE;
-
- for (i = 0; i < (LE32(responseBase->PIDSize) >> 1) - 2; i++)
- {
- if (!responseBase->KmsPID[i]) return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- * "Decrypts" a KMS v4 response. Actually just copies to a fixed size buffer
- */
-RESPONSE_RESULT DecryptResponseV4(RESPONSE_V4* response_v4, const int responseSize, BYTE* const rawResponse, const BYTE* const rawRequest)
-{
- int copySize =
- V4_PRE_EPID_SIZE +
- (LE32(((RESPONSE_V4*)rawResponse)->ResponseBase.PIDSize) <= PID_BUFFER_SIZE << 1 ?
- LE32(((RESPONSE_V4*)rawResponse)->ResponseBase.PIDSize) :
- PID_BUFFER_SIZE << 1);
-
- int messageSize = copySize + V4_POST_EPID_SIZE;
-
- memcpy(response_v4, rawResponse, copySize);
- memcpy(&response_v4->ResponseBase.CMID, rawResponse + copySize, responseSize - copySize);
-
- // ensure PID is null terminated
- response_v4->ResponseBase.KmsPID[PID_BUFFER_SIZE-1] = 0;
-
- uint8_t* mac = rawResponse + messageSize;
- AesCmacV4(rawResponse, messageSize, mac);
-
- REQUEST_V4* request_v4 = (REQUEST_V4*)rawRequest;
- RESPONSE_RESULT result;
-
- result.mask = (DWORD)~0;
- result.PidLengthOK = checkPidLength((RESPONSE*)rawResponse);
- result.VersionOK = response_v4->ResponseBase.Version == request_v4->RequestBase.Version;
- result.HashOK = !memcmp(&response_v4->MAC, mac, sizeof(response_v4->MAC));
- result.TimeStampOK = !memcmp(&response_v4->ResponseBase.ClientTime, &request_v4->RequestBase.ClientTime, sizeof(FILETIME));
- result.ClientMachineIDOK = !memcmp(&response_v4->ResponseBase.CMID, &request_v4->RequestBase.CMID, sizeof(GUID));
- result.effectiveResponseSize = responseSize;
- result.correctResponseSize = sizeof(RESPONSE_V4) - sizeof(response_v4->ResponseBase.KmsPID) + LE32(response_v4->ResponseBase.PIDSize);
-
- return result;
-}
-
-
-static RESPONSE_RESULT VerifyResponseV6(RESPONSE_RESULT result, const AesCtx* Ctx, RESPONSE_V6* response_v6, REQUEST_V6* request_v6, BYTE* const rawResponse)
-{
- // Check IVs
- result.IVsOK = !memcmp // In V6 the XoredIV is actually the request IV
- (
- response_v6->XoredIVs,
- request_v6->IV,
- sizeof(response_v6->XoredIVs)
- );
-
- result.IVnotSuspicious = !!memcmp // If IVs are identical, it is obviously an emulator
- (
- request_v6->IV,
- response_v6->IV,
- sizeof(request_v6->IV)
- );
-
- // Check Hmac
- int_fast8_t tolerance;
- BYTE OldHmac[sizeof(response_v6->HMAC)];
-
- result.HmacSha256OK = FALSE;
-
- memcpy // Save received HMAC to compare with calculated HMAC later
- (
- OldHmac,
- response_v6->HMAC,
- sizeof(response_v6->HMAC)
- );
-
- //AesEncryptBlock(Ctx, Response_v6->IV); // CreateV6Hmac needs original IV as received over the network
-
- for (tolerance = -1; tolerance < 2; tolerance++)
- {
- CreateV6Hmac
- (
- rawResponse + sizeof(response_v6->Version), // Pointer to start of the encrypted part of the response
- (size_t)result.correctResponseSize - V6_UNENCRYPTED_SIZE, // size of the encrypted part
- tolerance // tolerance -1, 0, or +1
- );
-
- if
- ((
- result.HmacSha256OK = !memcmp // Compare both HMACs
- (
- OldHmac,
- rawResponse + (size_t)result.correctResponseSize - sizeof(response_v6->HMAC),
- sizeof(OldHmac)
- )
- ))
- {
- break;
- }
- }
- return result;
-}
-
-
-static RESPONSE_RESULT VerifyResponseV5(RESPONSE_RESULT result, REQUEST_V5* request_v5, RESPONSE_V5* response_v5)
-{
- // Check IVs: in V5 (and only v5) request and response IVs must match
- result.IVsOK = !memcmp(request_v5->IV, response_v5->IV, sizeof(request_v5->IV));
-
- // V5 has no Hmac, always set to TRUE
- result.HmacSha256OK = TRUE;
-
- return result;
-}
-
-
-/*
- * Decrypts a KMS v5 or v6 response received from a server.
- * hwid must supply a valid 16 byte buffer for v6. hwid is ignored in v5
- */
-RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BYTE* const response, const BYTE* const rawRequest, BYTE* hwid)
-{
- RESPONSE_RESULT result;
- result.mask = ~0; // Set all bits in the results mask to 1. Assume success first.
- result.effectiveResponseSize = responseSize;
-
- int copySize1 =
- sizeof(response_v6->Version);
-
- // Decrypt KMS Server Response (encrypted part starts after RequestIV)
- responseSize -= copySize1;
-
- AesCtx Ctx;
- 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);
-
- // Check padding
- BYTE* lastPadByte = response + (size_t)result.effectiveResponseSize - 1;
-
- // Must be from 1 to 16
- if (!*lastPadByte || *lastPadByte > AES_BLOCK_BYTES)
- {
- result.DecryptSuccess = FALSE;
- return result;
- }
-
- // Check if pad bytes are all the same
- BYTE* padByte;
- for (padByte = lastPadByte - *lastPadByte + 1; padByte < lastPadByte; padByte++)
- if (*padByte != *lastPadByte)
- {
- result.DecryptSuccess = FALSE;
- return result;
- }
-
- // Add size of Version, KmsPIDLen and variable size PID
- DWORD pidSize = LE32(((RESPONSE_V6*) response)->ResponseBase.PIDSize);
-
- copySize1 +=
- V6_UNENCRYPTED_SIZE +
- sizeof(response_v6->ResponseBase.PIDSize) +
- (pidSize <= PID_BUFFER_SIZE << 1 ? pidSize : PID_BUFFER_SIZE << 1);
-
- // Copy part 1 of response up to variable sized PID
- memcpy(response_v6, response, copySize1);
-
- // ensure PID is null terminated
- response_v6->ResponseBase.KmsPID[PID_BUFFER_SIZE - 1] = 0;
-
- // Copy part 2
- size_t copySize2 = v6 ? V6_POST_EPID_SIZE : V5_POST_EPID_SIZE;
- memcpy(&response_v6->ResponseBase.CMID, response + copySize1, copySize2);
-
- // Decrypting the response is finished here. Now we check the results for validity
- // A basic client doesn't need the stuff below this comment but we want to use vlmcs
- // as a debug tool for KMS emulators.
-
- REQUEST_V6* request_v6 = (REQUEST_V6*) rawRequest;
- DWORD decryptSize = sizeof(request_v6->IV) + sizeof(request_v6->RequestBase) + sizeof(request_v6->Pad);
-
- AesDecryptCbc(&Ctx, NULL, request_v6->IV, decryptSize);
-
- // Check that all version informations are the same
- result.VersionOK =
- request_v6->Version == response_v6->ResponseBase.Version &&
- request_v6->Version == response_v6->Version &&
- request_v6->Version == request_v6->RequestBase.Version;
-
- // Check Base Request
- result.PidLengthOK = checkPidLength(&((RESPONSE_V6*) response)->ResponseBase);
- result.TimeStampOK = !memcmp(&response_v6->ResponseBase.ClientTime, &request_v6->RequestBase.ClientTime, sizeof(FILETIME));
- 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)];
-
- 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));
-
- // size before encryption (padding not included)
- result.correctResponseSize =
- (v6 ? sizeof(RESPONSE_V6) : sizeof(RESPONSE_V5))
- - sizeof(response_v6->ResponseBase.KmsPID)
- + LE32(response_v6->ResponseBase.PIDSize);
-
- // Version specific stuff
- if (v6)
- {
- // Copy the HwId
- memcpy(hwid, response_v6->HwId, sizeof(response_v6->HwId));
-
- // Verify the V6 specific part of the response
- result = VerifyResponseV6(result, &Ctx, response_v6, request_v6, response);
- }
- else // V5
- {
- // Verify the V5 specific part of the response
- result = VerifyResponseV5(result, request_v6, (RESPONSE_V5*)response_v6);
- }
-
- // padded size after encryption
- result.correctResponseSize += (~(result.correctResponseSize - sizeof(response_v6->ResponseBase.Version)) & 0xf) + 1;
-
- return result;
-}
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "endian.h"
-
-#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \
- && defined(BS16) && defined(BS32) && defined(BS64)
-
-#else // ! defined(__BYTE_ORDER)
-
-void PUT_UAA64BE(void *p, unsigned long long v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- _p[ 0 ] = v >> 56;
- _p[ 1 ] = v >> 48;
- _p[ 2 ] = v >> 40;
- _p[ 3 ] = v >> 32;
- _p[ 4 ] = v >> 24;
- _p[ 5 ] = v >> 16;
- _p[ 6 ] = v >> 8;
- _p[ 7 ] = v;
-}
-
-void PUT_UAA32BE(void *p, unsigned int v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- _p[ 0 ] = v >> 24;
- _p[ 1 ] = v >> 16;
- _p[ 2 ] = v >> 8;
- _p[ 3 ] = v;
-}
-
-void PUT_UAA16BE(void *p, unsigned short v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- _p[ 0 ] = v >> 8;
- _p[ 1 ] = v;
-}
-
-
-void PUT_UAA64LE(void *p, unsigned long long v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- _p[ 0 ] = v;
- _p[ 1 ] = v >> 8;
- _p[ 2 ] = v >> 16;
- _p[ 3 ] = v >> 24;
- _p[ 4 ] = v >> 32;
- _p[ 5 ] = v >> 40;
- _p[ 6 ] = v >> 48;
- _p[ 7 ] = v >> 56;
-}
-
-void PUT_UAA32LE(void *p, unsigned int v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- _p[ 0 ] = v;
- _p[ 1 ] = v >> 8;
- _p[ 2 ] = v >> 16;
- _p[ 3 ] = v >> 24;
-}
-
-void PUT_UAA16LE(void *p, unsigned short v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- _p[ 0 ] = v;
- _p[ 1 ] = v >> 8;
-}
-
-
-unsigned long long GET_UAA64BE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- return
- (unsigned long long)_p[ 0 ] << 56 |
- (unsigned long long)_p[ 1 ] << 48 |
- (unsigned long long)_p[ 2 ] << 40 |
- (unsigned long long)_p[ 3 ] << 32 |
- (unsigned long long)_p[ 4 ] << 24 |
- (unsigned long long)_p[ 5 ] << 16 |
- (unsigned long long)_p[ 6 ] << 8 |
- (unsigned long long)_p[ 7 ];
-
-}
-
-unsigned int GET_UAA32BE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- return
- (unsigned int)_p[ 0 ] << 24 |
- (unsigned int)_p[ 1 ] << 16 |
- (unsigned int)_p[ 2 ] << 8 |
- (unsigned int)_p[ 3 ];
-}
-
-unsigned short GET_UAA16BE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- return
- (unsigned short)_p[ 0 ] << 8 |
- (unsigned short)_p[ 1 ];
-}
-
-
-unsigned long long GET_UAA64LE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- return
- (unsigned long long)_p[ 0 ] |
- (unsigned long long)_p[ 1 ] << 8 |
- (unsigned long long)_p[ 2 ] << 16 |
- (unsigned long long)_p[ 3 ] << 24 |
- (unsigned long long)_p[ 4 ] << 32 |
- (unsigned long long)_p[ 5 ] << 40 |
- (unsigned long long)_p[ 6 ] << 48 |
- (unsigned long long)_p[ 7 ] << 56;
-
-}
-
-unsigned int GET_UAA32LE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- return
- (unsigned int)_p[ 0 ] |
- (unsigned int)_p[ 1 ] << 8 |
- (unsigned int)_p[ 2 ] << 16 |
- (unsigned int)_p[ 3 ] << 24;
-}
-
-unsigned short GET_UAA16LE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- return
- (unsigned short)_p[ 0 ] |
- (unsigned short)_p[ 1 ] << 8;
-}
-
-
-unsigned short BE16(unsigned short x)
-{
- return GET_UAA16BE(&x, 0);
-}
-
-unsigned short LE16(unsigned short x)
-{
- return GET_UAA16LE(&x, 0);
-}
-
-unsigned int BE32(unsigned int x)
-{
- return GET_UAA32BE(&x, 0);
-}
-
-unsigned int LE32(unsigned int x)
-{
- return GET_UAA32LE(&x, 0);
-}
-
-unsigned long long BE64(unsigned long long x)
-{
- return GET_UAA64BE(&x, 0);
-}
-
-inline unsigned long long LE64(unsigned long long x)
-{
- return GET_UAA64LE(&x, 0);
-}
-
-#endif // defined(__BYTE_ORDER)
-#ifndef _DEFAULT_SOURCE
-#define _DEFAULT_SOURCE
-#endif // _DEFAULT_SOURCE
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "output.h"
-#include "shared_globals.h"
-#include "endian.h"
-#include "helpers.h"
-
-#ifndef NO_LOG
-static void vlogger(const char *message, va_list args)
-{
- FILE *log;
-
- #ifdef _NTSERVICE
- if (!IsNTService && logstdout) log = stdout;
- #else
- if (logstdout) log = stdout;
- #endif
- else
- {
- if (fn_log == NULL) return;
-
- #ifndef _WIN32
- if (!strcmp(fn_log, "syslog"))
- {
- openlog("vlmcsd", LOG_CONS | LOG_PID, LOG_USER);
-
- ////PORTABILITY: vsyslog is not in Posix but virtually all Unixes have it
- vsyslog(LOG_INFO, message, args);
-
- closelog();
- return;
- }
- #endif // _WIN32
-
- log = fopen(fn_log, "a");
- if ( !log ) return;
- }
-
- time_t now = time(0);
-
- #ifdef USE_THREADS
- char mbstr[2048];
- #else
- char mbstr[24];
- #endif
-
- strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", localtime(&now));
-
- #ifndef USE_THREADS
-
- fprintf(log, "%s: ", mbstr);
- vfprintf(log, message, args);
- fflush(log);
-
- #else // USE_THREADS
-
- // We write everything to a string before we really log inside the critical section
- // so formatting the output can be concurrent
- strcat(mbstr, ": ");
- int len = strlen(mbstr);
- vsnprintf(mbstr + len, sizeof(mbstr) - len, message, args);
-
- lock_mutex(&logmutex);
- fputs(mbstr, log);
- fflush(log);
- unlock_mutex(&logmutex);
-
- #endif // USE_THREADS
- if (log != stdout) fclose(log);
-}
-
-
-// Always sends to log output
-int logger(const char *const fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- vlogger(fmt, args);
- va_end(args);
- return 0;
-}
-
-#endif //NO_LOG
-
-
-// Output to stderr if it is available or to log otherwise (e.g. if running as daemon/service)
-void printerrorf(const char *const fmt, ...)
-{
- va_list arglist;
-
- va_start(arglist, fmt);
-
- #ifndef NO_LOG
- #ifdef _NTSERVICE
- if (InetdMode || IsNTService)
- #else // !_NTSERVICE
- if (InetdMode)
- #endif // NTSERVIICE
- vlogger(fmt, arglist);
- else
- #endif //NO_LOG
- {
- vfprintf(stderr, fmt, arglist);
- fflush(stderr);
- }
-
- va_end(arglist);
-}
-
-
-// Always output to stderr
-int errorout(const char* fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- int i = vfprintf(stderr, fmt, args);
- va_end(args);
- fflush(stderr);
-
- return i;
-}
-
-
-static const char *LicenseStatusText[] =
-{
- "Unlicensed", "Licensed", "OOB grace", "OOT grace", "Non-Genuine", "Notification", "Extended grace"
-};
-
-
-void uuid2StringLE(const GUID *const guid, char *const string)
-{
- sprintf(string,
- #ifdef _WIN32
- "%08x-%04x-%04x-%04x-%012I64x",
- #else
- "%08x-%04x-%04x-%04x-%012llx",
- #endif
- (unsigned int)LE32( guid->Data1 ),
- (unsigned int)LE16( guid->Data2 ),
- (unsigned int)LE16( guid->Data3 ),
- (unsigned int)BE16( *(uint16_t*)guid->Data4 ),
- (unsigned long long)BE64(*(uint64_t*)(guid->Data4)) & 0xffffffffffffLL
- );
-}
-
-
-void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p)
-{
- char guidBuffer[GUID_STRING_LENGTH + 1];
- char WorkstationBuffer[3 * WORKSTATION_NAME_BUFFER];
- const char *productName;
- ProdListIndex_t index;
-
- p("Protocol version : %u.%u\n", LE16(Request->MajorVer), LE16(Request->MinorVer));
- p("Client is a virtual machine : %s\n", LE32(Request->VMInfo) ? "Yes" : "No");
- p("Licensing status : %u (%s)\n", (uint32_t)LE32(Request->LicenseStatus), LE32(Request->LicenseStatus) < _countof(LicenseStatusText) ? LicenseStatusText[LE32(Request->LicenseStatus)] : "Unknown");
- p("Remaining time (0 = forever) : %i minutes\n", (uint32_t)LE32(Request->BindingExpiration));
-
- uuid2StringLE(&Request->AppID, guidBuffer);
- productName = getProductNameLE(&Request->AppID, AppList, &index);
- p("Application ID : %s (%s)\n", guidBuffer, productName);
-
- uuid2StringLE(&Request->ActID, guidBuffer);
-
- #ifndef NO_EXTENDED_PRODUCT_LIST
- productName = getProductNameLE(&Request->ActID, ExtendedProductList, &index);
- #else
- productName = "Unknown";
- #endif
-
- p("Activation ID (Product) : %s (%s)\n", guidBuffer, productName);
-
- uuid2StringLE(&Request->KMSID, guidBuffer);
-
- #ifndef NO_BASIC_PRODUCT_LIST
- productName = getProductNameLE(&Request->KMSID, ProductList, &index);
- #else
- productName = "Unknown";
- #endif
-
- p("Key Management Service ID : %s (%s)\n", guidBuffer, productName);
-
- uuid2StringLE(&Request->CMID, guidBuffer);
- p("Client machine ID : %s\n", guidBuffer);
-
- uuid2StringLE(&Request->CMID_prev, guidBuffer);
- p("Previous client machine ID : %s\n", guidBuffer);
-
-
- char mbstr[64];
- time_t st;
- st = fileTimeToUnixTime(&Request->ClientTime);
- strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", gmtime(&st));
- p("Client request timestamp (UTC) : %s\n", mbstr);
-
- ucs2_to_utf8(Request->WorkstationName, WorkstationBuffer, WORKSTATION_NAME_BUFFER, sizeof(WorkstationBuffer));
-
- p("Workstation name : %s\n", WorkstationBuffer);
- 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)
-{
- char guidBuffer[GUID_STRING_LENGTH + 1];
- //SYSTEMTIME st;
-
- p("Protocol version : %u.%u\n", (uint32_t)LE16(response->MajorVer), (uint32_t)LE16(response->MinorVer));
- p("KMS host extended PID : %s\n", ePID);
- if (LE16(response->MajorVer) > 5)
-# ifndef _WIN32
- p("KMS host Hardware ID : %016llX\n", (unsigned long long)BE64(*(uint64_t*)hwid));
-# else // _WIN32
- p("KMS host Hardware ID : %016I64X\n", (unsigned long long)BE64(*(uint64_t*)hwid));
-# endif // WIN32
-
- uuid2StringLE(&response->CMID, guidBuffer);
- p("Client machine ID : %s\n", guidBuffer);
-
- char mbstr[64];
- time_t st;
-
- st = fileTimeToUnixTime(&response->ClientTime);
- strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", gmtime(&st));
- p("Client request timestamp (UTC) : %s\n", mbstr);
-
- p("KMS host current active clients : %u\n", (uint32_t)LE32(response->Count));
- p("Renewal interval policy : %u\n", (uint32_t)LE32(response->VLRenewalInterval));
- p("Activation interval policy : %u\n", (uint32_t)LE32(response->VLActivationInterval));
-}
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "shared_globals.h"
-
-int global_argc, multi_argc = 0;
-CARGV global_argv, multi_argv = NULL;
-const char *const Version = VERSION;
-DWORD VLActivationInterval = 60 * 2; // 2 hours
-DWORD VLRenewalInterval = 60 * 24 * 7; // 7 days
-int_fast8_t DisconnectImmediately = FALSE;
-const char *const cIPv4 = "IPv4";
-const char *const cIPv6 = "IPv6";
-
-#ifndef USE_MSRPC
-int_fast8_t UseMultiplexedRpc = TRUE;
-int_fast8_t UseRpcNDR64 = TRUE;
-int_fast8_t UseRpcBTFN = TRUE;
-#endif // USE_MSRPC
-
-#ifndef NO_SOCKETS
-const char *defaultport = "1688";
-#endif // NO_SOCKETS
-
-KmsResponseParam_t KmsResponseParameters[MAX_KMSAPPS];
-
-#if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
-int_fast8_t IsRestarted = FALSE;
-#endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
-
-#if !defined(NO_TIMEOUT) && !__minix__
-DWORD ServerTimeout = 30;
-#endif // !defined(NO_TIMEOUT) && !__minix__
-
-#if !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-#ifdef USE_MSRPC
-uint32_t MaxTasks = RPC_C_LISTEN_MAX_CALLS_DEFAULT;
-#else // !USE_MSRPC
-uint32_t MaxTasks = SEM_VALUE_MAX;
-#endif // !USE_MSRPC
-#endif // !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-
-#ifndef NO_LOG
-char *fn_log = NULL;
-int_fast8_t logstdout = 0;
-#ifndef NO_VERBOSE_LOG
-int_fast8_t logverbose = 0;
-#endif // NO_VERBOSE_LOG
-#endif // NO_LOG
-
-#ifndef NO_SOCKETS
-int_fast8_t nodaemon = 0;
-int_fast8_t InetdMode = 0;
-#else
-int_fast8_t nodaemon = 1;
-int_fast8_t InetdMode = 1;
-#endif
-
-#ifndef NO_RANDOM_EPID
-int_fast8_t RandomizationLevel = 1;
-uint16_t Lcid = 0;
-#endif
-
-#ifndef NO_SOCKETS
-SOCKET *SocketList;
-int numsockets = 0;
-
-#if !defined(NO_LIMIT) && !__minix__
-#ifndef _WIN32 // Posix
-sem_t *Semaphore;
-#else // _WIN32
-HANDLE Semaphore;
-#endif // _WIN32
-
-#endif // !defined(NO_LIMIT) && !__minix__
-#endif // NO_SOCKETS
-
-#ifdef _NTSERVICE
-int_fast8_t IsNTService = TRUE;
-int_fast8_t ServiceShutdown = FALSE;
-#endif // _NTSERVICE
-
-#ifndef NO_LOG
-#ifdef USE_THREADS
-#if !defined(_WIN32) && !defined(__CYGWIN__)
-pthread_mutex_t logmutex = PTHREAD_MUTEX_INITIALIZER;
-#else
-CRITICAL_SECTION logmutex;
-#endif // !defined(_WIN32) && !defined(__CYGWIN__)
-#endif // USE_THREADS
-#endif // NO_LOG
-
-
-
-
-
-/*
- * Helper functions used by other modules
- */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef _WIN32
-#include
-#endif // _WIN32
-#include
-#include
-#include
-#include
-#include "helpers.h"
-#include "output.h"
-#include "endian.h"
-#include "shared_globals.h"
-
-
-/*
- * UCS2 <-> UTF-8 functions
- * All functions use little endian UCS2 since we only need it to communicate with Windows via RPC
- */
-
-// Convert one character from UTF-8 to UCS2
-// Returns 0xffff, if utf-8 evaluates to > 0xfffe (outside basic multilingual pane)
-WCHAR utf8_to_ucs2_char (const unsigned char *input, const unsigned char **end_ptr)
-{
- *end_ptr = input;
- if (input[0] == 0)
- return ~0;
-
- if (input[0] < 0x80) {
- *end_ptr = input + 1;
- return LE16(input[0]);
- }
-
- if ((input[0] & 0xE0) == 0xE0) {
-
- if (input[1] == 0 || input[2] == 0)
- return ~0;
-
- *end_ptr = input + 3;
-
- return
- LE16((input[0] & 0x0F)<<12 |
- (input[1] & 0x3F)<<6 |
- (input[2] & 0x3F));
- }
-
- if ((input[0] & 0xC0) == 0xC0) {
- if (input[1] == 0)
- return ~0;
-
- *end_ptr = input + 2;
-
- return
- LE16((input[0] & 0x1F)<<6 |
- (input[1] & 0x3F));
- }
- return ~0;
-}
-
-// Convert one character from UCS2 to UTF-8
-// Returns length of UTF-8 char (1, 2 or 3) or -1 on error (UTF-16 outside UCS2)
-// char *utf8 must be large enough to hold 3 bytes
-int ucs2_to_utf8_char (const WCHAR ucs2_le, char *utf8)
-{
- const WCHAR ucs2 = LE16(ucs2_le);
-
- if (ucs2 < 0x80) {
- utf8[0] = ucs2;
- utf8[1] = '\0';
- return 1;
- }
-
- if (ucs2 >= 0x80 && ucs2 < 0x800) {
- utf8[0] = (ucs2 >> 6) | 0xC0;
- utf8[1] = (ucs2 & 0x3F) | 0x80;
- utf8[2] = '\0';
- return 2;
- }
-
- if (ucs2 >= 0x800 && ucs2 < 0xFFFF) {
-
- if (ucs2 >= 0xD800 && ucs2 <= 0xDFFF) {
- /* Ill-formed (UTF-16 ouside of BMP) */
- return -1;
- }
-
- utf8[0] = ((ucs2 >> 12) ) | 0xE0;
- utf8[1] = ((ucs2 >> 6 ) & 0x3F) | 0x80;
- utf8[2] = ((ucs2 ) & 0x3F) | 0x80;
- utf8[3] = '\0';
- return 3;
- }
-
- return -1;
-}
-
-
-// Converts UTF8 to UCS2. Returns size in bytes of the converted string or -1 on error
-size_t utf8_to_ucs2(WCHAR* const ucs2_le, const char* const utf8, const size_t maxucs2, const size_t maxutf8)
-{
- const unsigned char* current_utf8 = (unsigned char*)utf8;
- WCHAR* current_ucs2_le = ucs2_le;
-
- for (; *current_utf8; current_ucs2_le++)
- {
- size_t size = (char*)current_utf8 - utf8;
-
- if (size >= maxutf8) return (size_t)-1;
- if (((*current_utf8 & 0xc0) == 0xc0) && (size >= maxutf8 - 1)) return (size_t)-1;
- if (((*current_utf8 & 0xe0) == 0xe0) && (size >= maxutf8 - 2)) return (size_t)-1;
- if (current_ucs2_le - ucs2_le >= (intptr_t)maxucs2 - 1) return (size_t)-1;
-
- *current_ucs2_le = utf8_to_ucs2_char(current_utf8, ¤t_utf8);
- current_ucs2_le[1] = 0;
-
- if (*current_ucs2_le == (WCHAR)-1) return (size_t)-1;
- }
- return current_ucs2_le - ucs2_le;
-}
-
-// Converts UCS2 to UTF-8. Return TRUE or FALSE
-BOOL ucs2_to_utf8(const WCHAR* const ucs2_le, char* utf8, size_t maxucs2, size_t maxutf8)
-{
- char utf8_char[4];
- const WCHAR* current_ucs2 = ucs2_le;
- unsigned int index_utf8 = 0;
-
- for(*utf8 = 0; *current_ucs2; current_ucs2++)
- {
- if (current_ucs2 - ucs2_le > (intptr_t)maxucs2) return FALSE;
- int len = ucs2_to_utf8_char(*current_ucs2, utf8_char);
- if (index_utf8 + len > maxutf8) return FALSE;
- strncat(utf8, utf8_char, len);
- index_utf8+=len;
- }
-
- return TRUE;
-}
-
-/* End of UTF-8 <-> UCS2 conversion */
-
-
-// Checks, whether a string is a valid integer number between min and max. Returns TRUE or FALSE. Puts int value in *value
-BOOL stringToInt(const char *const szValue, const unsigned int min, const unsigned int max, unsigned int *const value)
-{
- char *nextchar;
-
- errno = 0;
- long long result = strtoll(szValue, &nextchar, 10);
-
- if (errno || result < (long long)min || result > (long long)max || *nextchar)
- {
- return FALSE;
- }
-
- *value = (unsigned int)result;
- return TRUE;
-}
-
-
-//Converts a String Guid to a host binary guid in host endianess
-int_fast8_t string2Uuid(const char *const restrict input, GUID *const restrict guid)
-{
- int i;
-
- if (strlen(input) < GUID_STRING_LENGTH) return FALSE;
- if (input[8] != '-' || input[13] != '-' || input[18] != '-' || input[23] != '-') return FALSE;
-
- for (i = 0; i < GUID_STRING_LENGTH; i++)
- {
- if (i == 8 || i == 13 || i == 18 || i == 23) continue;
-
- const char c = toupper((int)input[i]);
-
- if (c < '0' || c > 'F' || (c > '9' && c < 'A')) return FALSE;
- }
-
- char inputCopy[GUID_STRING_LENGTH + 1];
- strncpy(inputCopy, input, GUID_STRING_LENGTH + 1);
- inputCopy[8] = inputCopy[13] = inputCopy[18] = 0;
-
- hex2bin((BYTE*)&guid->Data1, inputCopy, 8);
- hex2bin((BYTE*)&guid->Data2, inputCopy + 9, 4);
- hex2bin((BYTE*)&guid->Data3, inputCopy + 14, 4);
- hex2bin(guid->Data4, input + 19, 16);
-
- guid->Data1 = BE32(guid->Data1);
- guid->Data2 = BE16(guid->Data2);
- guid->Data3 = BE16(guid->Data3);
- return TRUE;
-}
-
-
-// convert GUID to little-endian
-void LEGUID(GUID *const restrict out, const GUID* const restrict in)
-{
- #if __BYTE_ORDER != __LITTLE_ENDIAN
- out->Data1 = LE32(in->Data1);
- out->Data2 = LE16(in->Data2);
- out->Data3 = LE16(in->Data3);
- memcpy(out->Data4, in->Data4, sizeof(out->Data4));
- #else
- memcpy(out, in, sizeof(GUID));
- #endif
-}
-
-
-//Checks a command line argument if it is numeric and between min and max. Returns the numeric value or exits on error
-__pure unsigned int getOptionArgumentInt(const char o, const unsigned int min, const unsigned int max)
-{
- unsigned int result;
-
- if (!stringToInt(optarg, min, max, &result))
- {
- printerrorf("Fatal: Option \"-%c\" must be numeric between %u and %u.\n", o, min, max);
- exit(!0);
- }
-
- return result;
-}
-
-
-// Resets getopt() to start parsing from the beginning
-void optReset(void)
-{
- #if __minix__ || defined(__BSD__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
- optind = 1;
- optreset = 1; // Makes newer BSD getopt happy
- #elif defined(__UCLIBC__) // uClibc headers also define __GLIBC__ so be careful here
- optind = 0; // uClibc seeks compatibility with GLIBC
- #elif defined(__GLIBC__)
- optind = 0; // Makes GLIBC getopt happy
- #else // Standard for most systems
- optind = 1;
- #endif
-}
-
-
-#if defined(_WIN32) || defined(USE_MSRPC)
-
-// Returns a static message buffer containing text for a given Win32 error. Not thread safe (same as strerror)
-char* win_strerror(const int message)
-{
- #define STRERROR_BUFFER_SIZE 256
- static char buffer[STRERROR_BUFFER_SIZE];
-
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, message, 0, buffer, STRERROR_BUFFER_SIZE, NULL);
- return buffer;
-}
-
-#endif // defined(_WIN32) || defined(USE_MSRPC)
-
-
-/*
- * parses an address in the form host:[port] in addr
- * returns host and port in seperate strings
- */
-void parseAddress(char *const addr, char** szHost, char** szPort)
-{
- *szHost = addr;
-
-# ifndef NO_SOCKETS
- *szPort = (char*)defaultport;
-# else // NO_SOCKETS
- *szPort = "1688";
-# endif // NO_SOCKETS
-
- char *lastcolon = strrchr(addr, ':');
- char *firstcolon = strchr(addr, ':');
- char *closingbracket = strrchr(addr, ']');
-
- if (*addr == '[' && closingbracket) //Address in brackets
- {
- *closingbracket = 0;
- (*szHost)++;
-
- if (closingbracket[1] == ':')
- *szPort = closingbracket + 2;
- }
- else if (firstcolon && firstcolon == lastcolon) //IPv4 address or hostname with port
- {
- *firstcolon = 0;
- *szPort = firstcolon + 1;
- }
-}
-
-
-// Initialize random generator (needs to be done in each thread)
-void randomNumberInit()
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- srand((unsigned int)(tv.tv_sec ^ tv.tv_usec));
-}
-
-
-// We always exit immediately if any OOM condition occurs
-__noreturn void OutOfMemory(void)
-{
- errorout("Fatal: Out of memory");
- exit(!0);
-}
-
-
-void* vlmcsd_malloc(size_t len)
-{
- void* buf = malloc(len);
- if (!buf) OutOfMemory();
- return buf;
-}
-
-
-/*
- * Converts hex digits to bytes in big-endian order.
- * Ignores any non-hex characters
- */
-void hex2bin(BYTE *const bin, const char *hex, const size_t maxbin)
-{
- static const char *const hexdigits = "0123456789ABCDEF";
- char* nextchar;
- size_t i;
-
- for (i = 0; (i < 16) && utf8_to_ucs2_char((const unsigned char*)hex, (const unsigned char**)&nextchar) != (WCHAR)-1; hex = nextchar)
- {
- const char* pos = strchr(hexdigits, toupper((int)*hex));
- if (!pos) continue;
-
- if (!(i & 1)) bin[i >> 1] = 0;
- bin[i >> 1] |= (char)(pos - hexdigits);
- if (!(i & 1)) bin[i >> 1] <<= 4;
- i++;
- if (i >> 1 > maxbin) break;
- }
-}
-
-
-__pure BOOL getArgumentBool(int_fast8_t *result, const char *const argument)
-{
- if (
- !strncasecmp(argument, "true", 4) ||
- !strncasecmp(argument, "on", 2) ||
- !strncasecmp(argument, "yes", 3) ||
- !strncasecmp(argument, "1", 1)
- )
- {
- *result = TRUE;
- return TRUE;
- }
- else if (
- !strncasecmp(argument, "false", 5) ||
- !strncasecmp(argument, "off", 3) ||
- !strncasecmp(argument, "no", 2) ||
- !strncasecmp(argument, "0", 1)
- )
- {
- *result = FALSE;
- return TRUE;
- }
-
- return FALSE;
-}
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef USE_MSRPC
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include
-#ifndef _WIN32
-#include
-#include
-#include
-#include
-#include
-#endif // WIN32
-
-#include "network.h"
-#include "endian.h"
-#include "output.h"
-#include "helpers.h"
-#include "shared_globals.h"
-#include "rpc.h"
-
-
-#ifndef _WIN32
-typedef ssize_t (*sendrecv_t)(int, void*, size_t, int);
-#else
-typedef int (WINAPI *sendrecv_t)(SOCKET, void*, int, int);
-#endif
-
-
-// Send or receive a fixed number of bytes regardless if received in one or more chunks
-int_fast8_t sendrecv(SOCKET sock, BYTE *data, int len, int_fast8_t do_send)
-{
- int n;
- sendrecv_t f = do_send
- ? (sendrecv_t) send
- : (sendrecv_t) recv;
-
- do
- {
- n = f(sock, data, len, 0);
- }
- while (
- ( n < 0 && socket_errno == VLMCSD_EINTR ) || ( n > 0 && ( data += n, (len -= n) > 0 ) ));
-
- return ! len;
-}
-
-
-static int_fast8_t ip2str(char *restrict result, const size_t resultLength, const struct sockaddr *const restrict socketAddress, const socklen_t socketLength)
-{
- static const char *const fIPv4 = "%s:%s";
- static const char *const fIPv6 = "[%s]:%s";
- char ipAddress[64], portNumber[8];
-
- if (getnameinfo
- (
- socketAddress,
- socketLength,
- ipAddress,
- sizeof(ipAddress),
- portNumber,
- sizeof(portNumber),
- NI_NUMERICHOST | NI_NUMERICSERV
- ))
- {
- return FALSE;
- }
-
- if ((unsigned int)snprintf(result, resultLength, socketAddress->sa_family == AF_INET6 ? fIPv6 : fIPv4, ipAddress, portNumber) > resultLength) return FALSE;
- return TRUE;
-}
-
-
-static int_fast8_t getSocketList(struct addrinfo **saList, const char *const addr, const int flags, const int AddressFamily)
-{
- int status;
- char *szHost, *szPort;
- size_t len = strlen(addr) + 1;
-
- // Don't alloca too much
- if (len > 264) return FALSE;
-
- char *addrcopy = (char*)alloca(len);
- memcpy(addrcopy, addr, len);
-
- parseAddress(addrcopy, &szHost, &szPort);
-
- struct addrinfo hints;
-
- memset(&hints, 0, sizeof(struct addrinfo));
-
- hints.ai_family = AddressFamily;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_flags = flags;
-
- if ((status = getaddrinfo(szHost, szPort, &hints, saList)))
- {
- printerrorf("Warning: %s: %s\n", addr, gai_strerror(status));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-static int_fast8_t setBlockingEnabled(SOCKET fd, int_fast8_t blocking)
-{
- if (fd == INVALID_SOCKET) return FALSE;
-
- #ifdef _WIN32
-
- unsigned long mode = blocking ? 0 : 1;
- return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? TRUE : FALSE;
-
- #else // POSIX
-
- int flags = fcntl(fd, F_GETFL, 0);
-
- if (flags < 0) return FALSE;
-
- flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
- return (fcntl(fd, F_SETFL, flags) == 0) ? TRUE : FALSE;
-
- #endif // POSIX
-}
-
-
-int_fast8_t isDisconnected(const SOCKET s)
-{
- char buffer[1];
-
- if (!setBlockingEnabled(s, FALSE)) return TRUE;
-
- int n = recv(s, buffer, 1, MSG_PEEK);
-
- if (!setBlockingEnabled(s, TRUE)) return TRUE;
- if (n == 0) return TRUE;
-
- return FALSE;
-}
-
-
-// Connect to TCP address addr (e.g. "kms.example.com:1688") and return an
-// open socket for the connection if successful or INVALID_SOCKET otherwise
-SOCKET connectToAddress(const char *const addr, const int AddressFamily, int_fast8_t showHostName)
-{
- struct addrinfo *saList, *sa;
- SOCKET s = INVALID_SOCKET;
- char szAddr[128];
-
- if (!getSocketList(&saList, addr, 0, AddressFamily)) return INVALID_SOCKET;
-
- for (sa = saList; sa; sa = sa->ai_next)
- {
- // struct sockaddr_in* addr4 = (struct sockaddr_in*)sa->ai_addr;
- // struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sa->ai_addr;
-
- if (ip2str(szAddr, sizeof(szAddr), sa->ai_addr, sa->ai_addrlen))
- {
- if (showHostName)
- printf("Connecting to %s (%s) ... ", addr, szAddr);
- else
- printf("Connecting to %s ... ", szAddr);
-
- fflush(stdout);
- }
-
- s = socket(sa->ai_family, SOCK_STREAM, IPPROTO_TCP);
-
-# if !defined(NO_TIMEOUT) && !__minix__
-# ifndef _WIN32 // Standard Posix timeout structure
-
- struct timeval to;
- to.tv_sec = 10;
- to.tv_usec = 0;
-
-# else // Windows requires a DWORD with milliseconds
-
- DWORD to = 10000;
-
-# endif // _WIN32
-
- setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to));
- setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
-# endif // !defined(NO_TIMEOUT) && !__minix__
-
- if (!connect(s, sa->ai_addr, sa->ai_addrlen))
- {
- printf("successful\n");
- break;
- }
-
- errorout("%s\n", socket_errno == VLMCSD_EINPROGRESS ? "Timed out" : vlmcsd_strerror(socket_errno));
-
- socketclose(s);
- s = INVALID_SOCKET;
- }
-
- freeaddrinfo(saList);
- return s;
-}
-
-
-#ifndef NO_SOCKETS
-
-// Create a Listening socket for addrinfo sa and return socket s
-// szHost and szPort are for logging only
-static int listenOnAddress(const struct addrinfo *const ai, SOCKET *s)
-{
- int error;
- char ipstr[64];
-
- ip2str(ipstr, sizeof(ipstr), ai->ai_addr, ai->ai_addrlen);
-
- //*s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- *s = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
-
- if (*s == INVALID_SOCKET)
- {
- error = socket_errno;
- printerrorf("Warning: %s error. %s\n", ai->ai_family == AF_INET6 ? cIPv6 : cIPv4, vlmcsd_strerror(error));
- return error;
- }
-
-# if !defined(_WIN32) && !defined(NO_SIGHUP)
-
- int flags = fcntl(*s, F_GETFD, 0);
-
- if (flags != -1)
- {
- flags |= FD_CLOEXEC;
- fcntl(*s, F_SETFD, flags);
- }
-# ifdef _PEDANTIC
- else
- {
- printerrorf("Warning: Could not set FD_CLOEXEC flag on %s: %s\n", ipstr, vlmcsd_strerror(errno));
- }
-# endif // _PEDANTIC
-
-# endif // !defined(_WIN32) && !defined(NO_SIGHUP)
-
- BOOL socketOption = TRUE;
-
- // fix for lame tomato toolchain
-# ifndef IPV6_V6ONLY
-# ifdef __linux__
-# define IPV6_V6ONLY (26)
-# endif // __linux__
-# endif // IPV6_V6ONLY
-
-# ifdef IPV6_V6ONLY
- if (ai->ai_family == AF_INET6) setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_t)&socketOption, sizeof(socketOption));
-# endif
-
-# ifndef _WIN32
- setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (sockopt_t)&socketOption, sizeof(socketOption));
-# endif
-
- if (bind(*s, ai->ai_addr, ai->ai_addrlen) || listen(*s, SOMAXCONN))
- {
- error = socket_errno;
- printerrorf("Warning: %s: %s\n", ipstr, vlmcsd_strerror(error));
- socketclose(*s);
- return error;
- }
-
-# ifndef NO_LOG
- logger("Listening on %s\n", ipstr);
-# endif
-
- return 0;
-}
-
-
-// Adds a listening socket for an address string,
-// e.g. 127.0.0.1:1688 or [2001:db8:dead:beef::1]:1688
-BOOL addListeningSocket(const char *const addr)
-{
- struct addrinfo *aiList, *ai;
- int result = FALSE;
- SOCKET *s = SocketList + numsockets;
-
- if (getSocketList(&aiList, addr, AI_PASSIVE | AI_NUMERICHOST, AF_UNSPEC))
- {
- for (ai = aiList; ai; ai = ai->ai_next)
- {
- // struct sockaddr_in* addr4 = (struct sockaddr_in*)sa->ai_addr;
- // struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sa->ai_addr;
-
- if (numsockets >= FD_SETSIZE)
- {
- #ifdef _PEDANTIC // Do not report this error in normal builds to keep file size low
- printerrorf("Warning: Cannot listen on %s. Your OS only supports %u listening sockets in an FD_SET.\n", addr, FD_SETSIZE);
- #endif
- break;
- }
-
- if (!listenOnAddress(ai, s))
- {
- numsockets++;
- result = TRUE;
- }
- }
-
- freeaddrinfo(aiList);
- }
- return result;
-}
-
-
-// Just create some dummy sockets to see if we have a specific protocol (IPv4 or IPv6)
-__pure int_fast8_t checkProtocolStack(const int addressfamily)
-{
- SOCKET s; // = INVALID_SOCKET;
-
- s = socket(addressfamily, SOCK_STREAM, 0);
- int_fast8_t success = (s != INVALID_SOCKET);
-
- socketclose(s);
- return success;
-}
-
-
-// Build an fd_set of all listening socket then use select to wait for an incoming connection
-static SOCKET network_accept_any()
-{
- fd_set ListeningSocketsList;
- SOCKET maxSocket, sock;
- int i;
- int status;
-
- FD_ZERO(&ListeningSocketsList);
- maxSocket = 0;
-
- for (i = 0; i < numsockets; i++)
- {
- FD_SET(SocketList[i], &ListeningSocketsList);
- if (SocketList[i] > maxSocket) maxSocket = SocketList[i];
- }
-
- status = select(maxSocket + 1, &ListeningSocketsList, NULL, NULL, NULL);
-
- if (status < 0) return INVALID_SOCKET;
-
- sock = INVALID_SOCKET;
-
- for (i = 0; i < numsockets; i++)
- {
- if (FD_ISSET(SocketList[i], &ListeningSocketsList))
- {
- sock = SocketList[i];
- break;
- }
- }
-
- if (sock == INVALID_SOCKET)
- return INVALID_SOCKET;
- else
- return accept(sock, NULL, NULL);
-}
-
-
-void closeAllListeningSockets()
-{
- int i;
-
- for (i = 0; i < numsockets; i++)
- {
- shutdown(SocketList[i], VLMCSD_SHUT_RDWR);
- socketclose(SocketList[i]);
- }
-}
-#endif // NO_SOCKETS
-
-
-static void serveClient(const SOCKET s_client, const DWORD RpcAssocGroup)
-{
-# if !defined(NO_TIMEOUT) && !__minix__
-
-# ifndef _WIN32 // Standard Posix timeout structure
-
- struct timeval to;
- to.tv_sec = ServerTimeout;
- to.tv_usec = 0;
-
- #else // Windows requires a DWORD with milliseconds
-
- DWORD to = ServerTimeout * 1000;
-
-# endif // _WIN32
-
-# if !defined(NO_LOG) && defined(_PEDANTIC)
-
- int result =
- setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to)) ||
- setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
-
- if (result) logger("Warning: Set timeout failed: %s\n", vlmcsd_strerror(socket_errno));
-
-# else // !(!defined(NO_LOG) && defined(_PEDANTIC))
-
- setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to));
- setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
-
-# endif // !(!defined(NO_LOG) && defined(_PEDANTIC))
-
-# endif // !defined(NO_TIMEOUT) && !__minix__
-
- char ipstr[64];
- socklen_t len;
- struct sockaddr_storage addr;
-
- len = sizeof addr;
-
- if (getpeername(s_client, (struct sockaddr*)&addr, &len) ||
- !ip2str(ipstr, sizeof(ipstr), (struct sockaddr*)&addr, len))
- {
-# if !defined(NO_LOG) && defined(_PEDANTIC)
- logger("Fatal: Cannot determine client's IP address: %s\n", vlmcsd_strerror(errno));
-# endif // !defined(NO_LOG) && defined(_PEDANTIC)
- socketclose(s_client);
- return;
- }
-
-
-# ifndef NO_LOG
- const char *const connection_type = addr.ss_family == AF_INET6 ? cIPv6 : cIPv4;
- static const char *const cAccepted = "accepted";
- static const char *const cClosed = "closed";
- static const char *const fIP = "%s connection %s: %s.\n";
-
- logger(fIP, connection_type, cAccepted, ipstr);
- #endif // NO_LOG
-
- rpcServer(s_client, RpcAssocGroup, ipstr);
-
-# ifndef NO_LOG
- logger(fIP, connection_type, cClosed, ipstr);
-# endif // NO_LOG
-
- socketclose(s_client);
-}
-
-
-#ifndef NO_SOCKETS
-static void post_sem(void)
-{
- #if !defined(NO_LIMIT) && !__minix__
- if (!InetdMode && MaxTasks != SEM_VALUE_MAX)
- {
- semaphore_post(Semaphore);
- }
- #endif // !defined(NO_LIMIT) && !__minix__
-}
-
-
-static void wait_sem(void)
-{
- #if !defined(NO_LIMIT) && !__minix__
- if (!InetdMode && MaxTasks != SEM_VALUE_MAX)
- {
- semaphore_wait(Semaphore);
- }
- #endif // !defined(NO_LIMIT) && !__minix__
-}
-#endif // NO_SOCKETS
-
-#if defined(USE_THREADS) && !defined(NO_SOCKETS)
-
-#if defined(_WIN32) || defined(__CYGWIN__) // Win32 Threads
-static DWORD WINAPI serveClientThreadProc(PCLDATA clData)
-#else // Posix threads
-static void *serveClientThreadProc (PCLDATA clData)
-#endif // Thread proc is identical in WIN32 and Posix threads
-{
- serveClient(clData->socket, clData->RpcAssocGroup);
- free(clData);
- post_sem();
-
- return 0;
-}
-
-#endif // USE_THREADS
-
-
-#ifndef NO_SOCKETS
-
-#if defined(USE_THREADS) && (defined(_WIN32) || defined(__CYGWIN__)) // Windows Threads
-static int serveClientAsyncWinThreads(const PCLDATA thr_CLData)
-{
- wait_sem();
-
- HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)serveClientThreadProc, thr_CLData, 0, NULL);
-
- if (h)
- CloseHandle(h);
- else
- {
- socketclose(thr_CLData->socket);
- free(thr_CLData);
- post_sem();
- return GetLastError();
- }
-
- return NO_ERROR;
-}
-#endif // defined(USE_THREADS) && defined(_WIN32) // Windows Threads
-
-
-#if defined(USE_THREADS) && !defined(_WIN32) && !defined(__CYGWIN__) // Posix Threads
-static int ServeClientAsyncPosixThreads(const PCLDATA thr_CLData)
-{
- pthread_t p_thr;
- pthread_attr_t attr;
-
- wait_sem();
-
- // Must set detached state to avoid memory leak
- if (pthread_attr_init(&attr) ||
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) ||
- pthread_create(&p_thr, &attr, (void * (*)(void *))serveClientThreadProc, thr_CLData))
- {
- socketclose(thr_CLData->socket);
- free(thr_CLData);
- post_sem();
- return !0;
- }
-
- return 0;
-}
-#endif // defined(USE_THREADS) && !defined(_WIN32) // Posix Threads
-
-#ifndef USE_THREADS // fork() implementation
-static void ChildSignalHandler(const int signal)
-{
- if (signal == SIGHUP) return;
-
- post_sem();
-
- #ifndef NO_LOG
- logger("Warning: Child killed/crashed by %s\n", strsignal(signal));
- #endif // NO_LOG
-
- exit(!0);
-}
-
-static int ServeClientAsyncFork(const SOCKET s_client, const DWORD RpcAssocGroup)
-{
- int pid;
- wait_sem();
-
- if ((pid = fork()) < 0)
- {
- return errno;
- }
- else if ( pid )
- {
- // Parent process
- socketclose(s_client);
- return 0;
- }
- else
- {
- // Child process
-
- // Setup a Child Handler for most common termination signals
- struct sigaction sa;
-
- sa.sa_flags = 0;
- sa.sa_handler = ChildSignalHandler;
-
- static int signallist[] = { SIGHUP, SIGINT, SIGTERM, SIGSEGV, SIGILL, SIGFPE, SIGBUS };
-
- if (!sigemptyset(&sa.sa_mask))
- {
- uint_fast8_t i;
-
- for (i = 0; i < _countof(signallist); i++)
- {
- sigaction(signallist[i], &sa, NULL);
- }
- }
-
- serveClient(s_client, RpcAssocGroup);
- post_sem();
- exit(0);
- }
-}
-#endif
-
-
-int serveClientAsync(const SOCKET s_client, const DWORD RpcAssocGroup)
-{
- #ifndef USE_THREADS // fork() implementation
-
- return ServeClientAsyncFork(s_client, RpcAssocGroup);
-
- #else // threads implementation
-
- PCLDATA thr_CLData = (PCLDATA)vlmcsd_malloc(sizeof(CLDATA));
- thr_CLData->socket = s_client;
- thr_CLData->RpcAssocGroup = RpcAssocGroup;
-
- #if defined(_WIN32) || defined (__CYGWIN__) // Windows threads
-
- return serveClientAsyncWinThreads(thr_CLData);
-
- #else // Posix Threads
-
- return ServeClientAsyncPosixThreads(thr_CLData);
-
- #endif // Posix Threads
-
- #endif // USE_THREADS
-}
-
-#endif // NO_SOCKETS
-
-
-int runServer()
-{
- DWORD RpcAssocGroup = rand32();
-
- // If compiled for inetd-only mode just serve the stdin socket
- #ifdef NO_SOCKETS
- serveClient(STDIN_FILENO, RpcAssocGroup);
- return 0;
- #else
- // In inetd mode just handle the stdin socket
- if (InetdMode)
- {
- serveClient(STDIN_FILENO, RpcAssocGroup);
- return 0;
- }
-
- // Standalone mode
- for (;;)
- {
- int error;
- SOCKET s_client;
-
- if ( (s_client = network_accept_any()) == INVALID_SOCKET )
- {
- error = socket_errno;
-
- if (error == VLMCSD_EINTR || error == VLMCSD_ECONNABORTED) continue;
-
- #ifdef _NTSERVICE
- if (ServiceShutdown) return 0;
- #endif
-
- #ifndef NO_LOG
- logger("Fatal: %s\n",vlmcsd_strerror(error));
- #endif
-
- return error;
- }
-
- RpcAssocGroup++;
- serveClientAsync(s_client, RpcAssocGroup);
- }
- #endif // NO_SOCKETS
-
- return 0;
-}
-
-#endif // USE_MSRPC
-#ifndef _DEFAULT_SOURCE
-#define _DEFAULT_SOURCE
-#endif // _DEFAULT_SOURCE
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef USE_MSRPC
-
-#include
-#include
-#include
-#include
-#include
-#include
-#if !defined(_WIN32)
-#include
-#include
-#endif
-#include "rpc.h"
-#include "output.h"
-#include "crypto.h"
-#include "endian.h"
-#include "helpers.h"
-#include "network.h"
-#include "shared_globals.h"
-
-/* Forwards */
-
-static int checkRpcHeader(const RPC_HEADER *const Header, const BYTE desiredPacketType, const PRINTFUNC p);
-
-
-/* Data definitions */
-
-// All GUIDs are defined as BYTE[16] here. No big-endian/little-endian byteswapping required.
-static const BYTE TransferSyntaxNDR32[] = {
- 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C, 0xC9, 0x11, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60
-};
-
-static const BYTE InterfaceUuid[] = {
- 0x75, 0x21, 0xc8, 0x51, 0x4e, 0x84, 0x50, 0x47, 0xB0, 0xD8, 0xEC, 0x25, 0x55, 0x55, 0xBC, 0x06
-};
-
-static const BYTE TransferSyntaxNDR64[] = {
- 0x33, 0x05, 0x71, 0x71, 0xba, 0xbe, 0x37, 0x49, 0x83, 0x19, 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36
-};
-
-static const BYTE BindTimeFeatureNegotiation[] = {
- 0x2c, 0x1c, 0xb7, 0x6c, 0x12, 0x98, 0x40, 0x45, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-
-//
-// Dispatch RPC payload to kms.c
-//
-typedef int (*CreateResponse_t)(const void *const, void *const, const char* const);
-
-static const struct {
- unsigned int RequestSize;
- CreateResponse_t CreateResponse;
-} _Versions[] = {
- { sizeof(REQUEST_V4), (CreateResponse_t) CreateResponseV4 },
- { sizeof(REQUEST_V6), (CreateResponse_t) CreateResponseV6 },
- { sizeof(REQUEST_V6), (CreateResponse_t) CreateResponseV6 }
-};
-
-RPC_FLAGS RpcFlags;
-static int_fast8_t firstPacketSent;
-
-//
-// RPC request (server)
-//
-#if defined(_PEDANTIC) && !defined(NO_LOG)
-static void CheckRpcRequest(const RPC_REQUEST64 *const Request, const unsigned int len, WORD* NdrCtx, WORD* Ndr64Ctx, WORD Ctx)
-{
- uint_fast8_t kmsMajorVersion;
- uint32_t requestSize = Ctx != *Ndr64Ctx ? sizeof(RPC_REQUEST) : sizeof(RPC_REQUEST64);
-
- if (len < requestSize)
- {
- logger("Fatal: RPC request (including header) must be at least %i bytes but is only %i bytes.\n",
- (int)(sizeof(RPC_HEADER) + requestSize),
- (int)(len + sizeof(RPC_HEADER))
- );
-
- return;
- }
-
- if (len < requestSize + sizeof(DWORD))
- {
- logger("Fatal: KMS Request too small to contain version info (less than 4 bytes).\n");
- return;
- }
-
- if (Ctx != *Ndr64Ctx)
- kmsMajorVersion = LE16(((WORD*)Request->Ndr.Data)[1]);
- else
- kmsMajorVersion = LE16(((WORD*)Request->Ndr64.Data)[1]);
-
- if (kmsMajorVersion > 6)
- {
- logger("Fatal: KMSv%u is not supported.\n", (unsigned int)kmsMajorVersion);
- }
- else
- {
- if (len >_Versions[kmsMajorVersion].RequestSize + requestSize)
- logger("Warning: %u excess bytes in RPC request.\n",
- len - _Versions[kmsMajorVersion].RequestSize
- );
- }
-
- if (Ctx != *Ndr64Ctx && Ctx != *NdrCtx)
- logger("Warning: Context id should be %u (NDR32) or %u (NDR64) but is %u.\n",
- (unsigned int)*NdrCtx,
- (unsigned int)*Ndr64Ctx,
- Ctx
- );
-
- if (Request->Opnum)
- logger("Warning: OpNum should be 0 but is %u.\n",
- (unsigned int)LE16(Request->Opnum)
- );
-
- if (LE32(Request->AllocHint) != len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr))
- logger("Warning: Allocation hint should be %u but is %u.\n",
- len + sizeof(Request->Ndr),
- LE32(Request->AllocHint)
- );
-
- if (Ctx != *Ndr64Ctx)
- {
- if (LE32(Request->Ndr.DataLength) != len - sizeof(RPC_REQUEST))
- logger("Warning: NDR32 data length field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST),
- LE32(Request->Ndr.DataLength)
- );
-
- if (LE32(Request->Ndr.DataSizeIs) != len - sizeof(RPC_REQUEST))
- logger("Warning: NDR32 data size field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST),
- LE32(Request->Ndr.DataSizeIs)
- );
- }
- else
- {
- if (LE64(Request->Ndr64.DataLength) != len - sizeof(RPC_REQUEST64))
- logger("Warning: NDR32 data length field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr),
- LE64(Request->Ndr64.DataLength)
- );
-
- if (LE64(Request->Ndr64.DataSizeIs) != len - sizeof(RPC_REQUEST64))
- logger("Warning: NDR32 data size field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST64),
- LE64(Request->Ndr64.DataSizeIs)
- );
- }
-}
-#endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
-/*
- * check RPC request for (somewhat) correct size
- * allow any size that does not cause CreateResponse to fail badly
- */
-static unsigned int checkRpcRequestSize(const RPC_REQUEST64 *const Request, const unsigned int requestSize, WORD* NdrCtx, WORD* Ndr64Ctx)
-{
- WORD Ctx = LE16(Request->ContextId);
-
-# if defined(_PEDANTIC) && !defined(NO_LOG)
- CheckRpcRequest(Request, requestSize, NdrCtx, Ndr64Ctx, Ctx);
-# endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
- // Anything that is smaller than a v4 request is illegal
- if (requestSize < sizeof(REQUEST_V4) + (Ctx != *Ndr64Ctx ? sizeof(RPC_REQUEST) : sizeof(RPC_REQUEST64))) return 0;
-
- // Get KMS major version
- uint_fast16_t _v;
-
- if (Ctx != *Ndr64Ctx)
- _v = LE16(((WORD*)Request->Ndr.Data)[1]) - 4;
- else
- _v = LE16(((WORD*)Request->Ndr64.Data)[1]) - 4;
-
- // Only KMS v4, v5 and v6 are supported
- if (_v >= vlmcsd_countof(_Versions))
- {
-# ifndef NO_LOG
- logger("Fatal: KMSv%i unsupported\n", _v + 4);
-# endif // NO_LOG
- return 0;
- }
-
- // Could check for equality but allow bigger requests to support buggy RPC clients (e.g. wine)
- // Buffer overrun is check by caller.
- return (requestSize >= _Versions[_v].RequestSize);
-}
-
-
-/*
- * Handles the actual KMS request from the client.
- * Calls KMS functions (CreateResponseV4 or CreateResponseV6) in kms.c
- * Returns size of the KMS response packet or 0 on failure.
- *
- * The RPC packet size (excluding header) is actually in Response->AllocHint
- */
-static int rpcRequest(const RPC_REQUEST64 *const Request, RPC_RESPONSE64 *const Response, const DWORD RpcAssocGroup_unused, const SOCKET sock_unused, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr)
-{
- uint_fast16_t _v;
- int ResponseSize;
- WORD Ctx = LE16(Request->ContextId);
- BYTE* requestData;
- BYTE* responseData;
- BYTE* pRpcReturnCode;
- int len;
-
- if (Ctx != *Ndr64Ctx)
- {
- requestData = (BYTE*)&Request->Ndr.Data;
- responseData = (BYTE*)&Response->Ndr.Data;
- }
- else
- {
- requestData = (BYTE*)&Request->Ndr64.Data;
- responseData = (BYTE*)&Response->Ndr64.Data;
- }
-
- _v = LE16(((WORD*)requestData)[1]) - 4;
-
- if (!(ResponseSize = _Versions[_v].CreateResponse(requestData, responseData, ipstr)))
- {
- return 0;
- }
-
- if (Ctx != *Ndr64Ctx)
- {
- Response->Ndr.DataSizeMax = LE32(0x00020000);
- Response->Ndr.DataLength = Response->Ndr.DataSizeIs = LE32(ResponseSize);
- len = ResponseSize + sizeof(Response->Ndr);
- }
- else
- {
- Response->Ndr64.DataSizeMax = LE64(0x00020000ULL);
- Response->Ndr64.DataLength = Response->Ndr64.DataSizeIs = LE64((uint64_t)ResponseSize);
- len = ResponseSize + sizeof(Response->Ndr64);
- }
-
- pRpcReturnCode = ((BYTE*)&Response->Ndr) + len;
- UA32(pRpcReturnCode) = 0; //LE32 not needed for 0
- len += sizeof(DWORD);
-
- // Pad zeros to 32-bit align (seems not neccassary but Windows RPC does it this way)
- int pad = ((~len & 3) + 1) & 3;
- memset(pRpcReturnCode + sizeof(DWORD), 0, pad);
- len += pad;
-
- Response->AllocHint = LE32(len);
- Response->ContextId = Request->ContextId;
-
- *((WORD*)&Response->CancelCount) = 0; // CancelCount + Pad1
-
- return len + 8;
-}
-
-
-#if defined(_PEDANTIC) && !defined(NO_LOG)
-static void CheckRpcBindRequest(const RPC_BIND_REQUEST *const Request, const unsigned int len)
-{
- uint_fast8_t i, HasTransferSyntaxNDR32 = FALSE;
- char guidBuffer1[GUID_STRING_LENGTH + 1], guidBuffer2[GUID_STRING_LENGTH + 1];
-
- uint32_t CapCtxItems = (len - sizeof(*Request) + sizeof(Request->CtxItems)) / sizeof(Request->CtxItems);
- DWORD NumCtxItems = LE32(Request->NumCtxItems);
-
- if (NumCtxItems < CapCtxItems) // Can't be too small because already handled by RpcBindSize
- logger("Warning: Excess bytes in RPC bind request.\n");
-
- for (i = 0; i < NumCtxItems; i++)
- {
- if (!IsEqualGUID(&Request->CtxItems[i].InterfaceUUID, InterfaceUuid))
- {
- uuid2StringLE((GUID*)&Request->CtxItems[i].InterfaceUUID, guidBuffer1);
- uuid2StringLE((GUID*)InterfaceUuid, guidBuffer2);
- logger("Warning: Interface UUID is %s but should be %s in Ctx item %u.\n", guidBuffer1, guidBuffer2, (unsigned int)i);
- }
-
- if (Request->CtxItems[i].NumTransItems != LE16(1))
- logger("Fatal: %u NDR32 transfer items detected in Ctx item %u, but only one is supported.\n",
- (unsigned int)LE16(Request->CtxItems[i].NumTransItems), (unsigned int)i
- );
-
- if (Request->CtxItems[i].InterfaceVerMajor != LE16(1) || Request->CtxItems[i].InterfaceVerMinor != 0)
- logger("Warning: NDR32 Interface version is %u.%u but should be 1.0.\n",
- (unsigned int)LE16(Request->CtxItems[i].InterfaceVerMajor),
- (unsigned int)LE16(Request->CtxItems[i].InterfaceVerMinor)
- );
-
- if (Request->CtxItems[i].ContextId != LE16((WORD)i))
- logger("Warning: context id of Ctx item %u is %u.\n", (unsigned int)i, (unsigned int)Request->CtxItems[i].ContextId);
-
- if ( IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
- {
- HasTransferSyntaxNDR32 = TRUE;
-
- if (Request->CtxItems[i].SyntaxVersion != LE32(2))
- logger("NDR32 transfer syntax version is %u but should be 2.\n", LE32(Request->CtxItems[i].SyntaxVersion));
- }
- else if ( IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
- {
- if (Request->CtxItems[i].SyntaxVersion != LE32(1))
- logger("NDR64 transfer syntax version is %u but should be 1.\n", LE32(Request->CtxItems[i].SyntaxVersion));
- }
- else if (!memcmp(BindTimeFeatureNegotiation, (BYTE*)(&Request->CtxItems[i].TransferSyntax), 8))
- {
- if (Request->CtxItems[i].SyntaxVersion != LE32(1))
- logger("BTFN syntax version is %u but should be 1.\n", LE32(Request->CtxItems[i].SyntaxVersion));
- }
- }
-
- if (!HasTransferSyntaxNDR32)
- logger("Warning: RPC bind request has no NDR32 CtxItem.\n");
-}
-#endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
-
-/*
- * Check, if we receive enough bytes to return a valid RPC bind response
- */
-static unsigned int checkRpcBindSize(const RPC_BIND_REQUEST *const Request, const unsigned int RequestSize, WORD* NdrCtx, WORD* Ndr64Ctx)
-{
- if ( RequestSize < sizeof(RPC_BIND_REQUEST) ) return FALSE;
-
- unsigned int _NumCtxItems = LE32(Request->NumCtxItems);
-
- if ( RequestSize < sizeof(RPC_BIND_REQUEST) - sizeof(Request->CtxItems[0]) + _NumCtxItems * sizeof(Request->CtxItems[0]) ) return FALSE;
-
- #if defined(_PEDANTIC) && !defined(NO_LOG)
- CheckRpcBindRequest(Request, RequestSize);
- #endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
- return TRUE;
-}
-
-
-/*
- * Accepts a bind or alter context request from the client and composes the bind response.
- * Needs the socket because the tcp port number is part of the response.
- * len is not used here.
- *
- * Returns TRUE on success.
- */
-static int rpcBind(const RPC_BIND_REQUEST *const Request, RPC_BIND_RESPONSE* Response, const DWORD RpcAssocGroup, const SOCKET sock, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr_unused)
-{
- unsigned int i, _st = FALSE;
- DWORD numCtxItems = LE32(Request->NumCtxItems);
- int_fast8_t IsNDR64possible = FALSE;
- uint_fast8_t portNumberSize;
-
- socklen_t socklen;
- struct sockaddr_storage addr;
-
- // M$ RPC does not do this. Pad bytes contain apparently random data
- // memset(Response->SecondaryAddress, 0, sizeof(Response->SecondaryAddress));
-
- socklen = sizeof addr;
-
- if (
- packetType == RPC_PT_ALTERCONTEXT_REQ ||
- getsockname(sock, (struct sockaddr*)&addr, &socklen) ||
- getnameinfo((struct sockaddr*)&addr, socklen, NULL, 0, (char*)Response->SecondaryAddress, sizeof(Response->SecondaryAddress), NI_NUMERICSERV))
- {
- portNumberSize = Response->SecondaryAddressLength = 0;
- }
- else
- {
- portNumberSize = strlen((char*)Response->SecondaryAddress) + 1;
- Response->SecondaryAddressLength = LE16(portNumberSize);
- }
-
- Response->MaxXmitFrag = Request->MaxXmitFrag;
- Response->MaxRecvFrag = Request->MaxRecvFrag;
- Response->AssocGroup = LE32(RpcAssocGroup);
-
- // This is really ugly (but efficient) code to support padding after the secondary address field
- if (portNumberSize < 3)
- {
- Response = (RPC_BIND_RESPONSE*)((BYTE*)Response - 4);
- }
-
- Response->NumResults = Request->NumCtxItems;
-
- if (UseRpcNDR64)
- {
- for (i = 0; i < numCtxItems; i++)
- {
- if ( IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
- {
- /*if (packetType == RPC_PT_BIND_REQ)*/
- *NdrCtx = LE16(Request->CtxItems[i].ContextId);
- }
-
- if ( IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
- {
- IsNDR64possible = TRUE;
-
- /*if (packetType == RPC_PT_BIND_REQ)*/
- *Ndr64Ctx = LE16(Request->CtxItems[i].ContextId);
- }
- }
- }
-
- for (i = 0; i < numCtxItems; i++)
- {
- memset(&Response->Results[i].TransferSyntax, 0, sizeof(GUID));
-
- if ( !IsNDR64possible && IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
- {
- Response->Results[i].SyntaxVersion = LE32(2);
- Response->Results[i].AckResult =
- Response->Results[i].AckReason = RPC_BIND_ACCEPT;
- memcpy(&Response->Results[i].TransferSyntax, TransferSyntaxNDR32, sizeof(GUID));
-
- _st = TRUE;
- }
- else if ( IsNDR64possible && IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
- {
- Response->Results[i].SyntaxVersion = LE32(1);
- Response->Results[i].AckResult =
- Response->Results[i].AckReason = RPC_BIND_ACCEPT;
- memcpy(&Response->Results[i].TransferSyntax, TransferSyntaxNDR64, sizeof(GUID));
-
- _st = TRUE;
- }
- else if ( UseRpcBTFN && !memcmp(BindTimeFeatureNegotiation, (BYTE*)(&Request->CtxItems[i].TransferSyntax), 8) )
- {
- Response->Results[i].SyntaxVersion = 0;
- Response->Results[i].AckResult = RPC_BIND_ACK;
-
- // Features requested are actually encoded in the GUID
- Response->Results[i].AckReason =
- ((WORD*)(&Request->CtxItems[i].TransferSyntax))[4] &
- (RPC_BTFN_SEC_CONTEXT_MULTIPLEX | RPC_BTFN_KEEP_ORPHAN);
- }
- else
- {
- Response->Results[i].SyntaxVersion = 0;
- Response->Results[i].AckResult =
- Response->Results[i].AckReason = RPC_BIND_NACK; // Unsupported
- }
- }
-
- if ( !_st ) return 0;
-
- return sizeof(RPC_BIND_RESPONSE) + numCtxItems * sizeof(((RPC_BIND_RESPONSE *)0)->Results[0]) - (portNumberSize < 3 ? 4 : 0);
-}
-
-
-//
-// Main RPC handling routine
-//
-typedef unsigned int (*GetResponseSize_t)(const void *const request, const unsigned int requestSize, WORD* NdrCtx, WORD* Ndr64Ctx);
-typedef int (*GetResponse_t)(const void* const request, void* response, const DWORD rpcAssocGroup, const SOCKET socket, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr);
-
-static const struct {
- BYTE ResponsePacketType;
- GetResponseSize_t CheckRequestSize;
- GetResponse_t GetResponse;
-}
-_Actions[] = {
- { RPC_PT_BIND_ACK, (GetResponseSize_t)checkRpcBindSize, (GetResponse_t) rpcBind },
- { RPC_PT_RESPONSE, (GetResponseSize_t)checkRpcRequestSize, (GetResponse_t) rpcRequest },
- { RPC_PT_ALTERCONTEXT_ACK, (GetResponseSize_t)checkRpcBindSize, (GetResponse_t) rpcBind },
-};
-
-
-/*
- * This is the main RPC server loop. Returns after KMS request has been serviced
- * or a timeout has occured.
- */
-void rpcServer(const SOCKET sock, const DWORD RpcAssocGroup, const char* const ipstr)
-{
- RPC_HEADER rpcRequestHeader;
- WORD NdrCtx = INVALID_NDR_CTX, Ndr64Ctx = INVALID_NDR_CTX;
-
- randomNumberInit();
-
- while (_recv(sock, &rpcRequestHeader, sizeof(rpcRequestHeader)))
- {
- //int_fast8_t _st;
- unsigned int request_len, response_len;
- uint_fast8_t _a;
-
- #if defined(_PEDANTIC) && !defined(NO_LOG)
- checkRpcHeader(&rpcRequestHeader, rpcRequestHeader.PacketType, &logger);
- #endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
- switch (rpcRequestHeader.PacketType)
- {
- case RPC_PT_BIND_REQ: _a = 0; break;
- case RPC_PT_REQUEST: _a = 1; break;
- case RPC_PT_ALTERCONTEXT_REQ: _a = 2; break;
- default: return;
- }
-
- request_len = LE16(rpcRequestHeader.FragLength) - sizeof(rpcRequestHeader);
-
- BYTE requestBuffer[MAX_REQUEST_SIZE + sizeof(RPC_RESPONSE64)];
- BYTE responseBuffer[MAX_RESPONSE_SIZE + sizeof(RPC_HEADER) + sizeof(RPC_RESPONSE64)];
-
- RPC_HEADER *rpcResponseHeader = (RPC_HEADER *)responseBuffer;
- RPC_RESPONSE* rpcResponse = (RPC_RESPONSE*)(responseBuffer + sizeof(rpcRequestHeader));
-
- // The request is larger than the buffer size
- if (request_len > MAX_REQUEST_SIZE + sizeof(RPC_REQUEST64)) return;
-
- // Unable to receive the complete request
- if (!_recv(sock, requestBuffer, request_len)) return;
-
- // Request is invalid
- if (!_Actions[_a].CheckRequestSize(requestBuffer, request_len, &NdrCtx, &Ndr64Ctx)) return;
-
- // Unable to create a valid response from request
- if (!(response_len = _Actions[_a].GetResponse(requestBuffer, rpcResponse, RpcAssocGroup, sock, &NdrCtx, &Ndr64Ctx, rpcRequestHeader.PacketType, ipstr))) return;
-
- response_len += sizeof(RPC_HEADER);
-
- memcpy(rpcResponseHeader, &rpcRequestHeader, sizeof(RPC_HEADER));
-
- rpcResponseHeader->FragLength = LE16(response_len);
- rpcResponseHeader->PacketType = _Actions[_a].ResponsePacketType;
-
- if (rpcResponseHeader->PacketType == RPC_PT_ALTERCONTEXT_ACK)
- rpcResponseHeader->PacketFlags = RPC_PF_FIRST | RPC_PF_LAST;
-
- if (!_send(sock, responseBuffer, response_len)) return;
-
- if (DisconnectImmediately && rpcResponseHeader->PacketType == RPC_PT_RESPONSE)
- shutdown(sock, VLMCSD_SHUT_RDWR);
- }
-}
-
-
-/* RPC client functions */
-
-static DWORD CallId = 2; // M$ starts with CallId 2. So we do the same.
-
-
-/*
- * Checks RPC header. Returns 0 on success.
- * This is mainly for debugging a non Microsoft KMS server that uses its own RPC code.
- */
-static int checkRpcHeader(const RPC_HEADER *const Header, const BYTE desiredPacketType, const PRINTFUNC p)
-{
- int status = 0;
-
- if (Header->PacketType != desiredPacketType)
- {
- p("Fatal: Received wrong RPC packet type. Expected %u but got %u\n",
- (uint32_t)desiredPacketType,
- Header->PacketType
- );
- status = !0;
- }
-
- if (Header->DataRepresentation != BE32(0x10000000))
- {
- p("Fatal: RPC response does not conform to Microsoft's limited support of DCE RPC\n");
- status = !0;
- }
-
- if (Header->AuthLength != 0)
- {
- p("Fatal: RPC response requests authentication\n");
- status = !0;
- }
-
- // vlmcsd does not support fragmented packets (not yet neccassary)
- if ( (Header->PacketFlags & (RPC_PF_FIRST | RPC_PF_LAST)) != (RPC_PF_FIRST | RPC_PF_LAST) )
- {
- p("Fatal: RPC packet flags RPC_PF_FIRST and RPC_PF_LAST are not both set.\n");
- status = !0;
- }
-
- if (Header->PacketFlags & RPC_PF_CANCEL_PENDING) p("Warning: %s should not be set\n", "RPC_PF_CANCEL_PENDING");
- if (Header->PacketFlags & RPC_PF_RESERVED) p("Warning: %s should not be set\n", "RPC_PF_RESERVED");
- if (Header->PacketFlags & RPC_PF_NOT_EXEC) p("Warning: %s should not be set\n", "RPC_PF_NOT_EXEC");
- if (Header->PacketFlags & RPC_PF_MAYBE) p("Warning: %s should not be set\n", "RPC_PF_MAYBE");
- if (Header->PacketFlags & RPC_PF_OBJECT) p("Warning: %s should not be set\n", "RPC_PF_OBJECT");
-
- if (Header->VersionMajor != 5 || Header->VersionMinor != 0)
- {
- p("Fatal: Expected RPC version 5.0 and got %u.%u\n", Header->VersionMajor, Header->VersionMinor);
- status = !0;
- }
-
- return status;
-}
-
-
-/*
- * Checks an RPC response header. Does basic header checks by calling checkRpcHeader()
- * and then does additional checks if response header complies with the respective request header.
- * PRINTFUNC p can be anything that has the same prototype as printf.
- * Returns 0 on success.
- */
-static int checkRpcResponseHeader(const RPC_HEADER *const ResponseHeader, const RPC_HEADER *const RequestHeader, const BYTE desiredPacketType, const PRINTFUNC p)
-{
- static int_fast8_t WineBugDetected = FALSE;
- int status = checkRpcHeader(ResponseHeader, desiredPacketType, p);
-
- if (desiredPacketType == RPC_PT_BIND_ACK)
- {
- if ((ResponseHeader->PacketFlags & RPC_PF_MULTIPLEX) != (RequestHeader->PacketFlags & RPC_PF_MULTIPLEX))
- {
- p("Warning: RPC_PF_MULTIPLEX of RPC request and response should match\n");
- }
- }
- else
- {
- if (ResponseHeader->PacketFlags & RPC_PF_MULTIPLEX)
- {
- p("Warning: %s should not be set\n", "RPC_PF_MULTIPLEX");
- }
- }
-
- if (!status && ResponseHeader->CallId == LE32(1))
- {
- if (!WineBugDetected)
- {
- p("Warning: Buggy RPC of Wine detected. Call Id of Response is always 1\n");
- WineBugDetected = TRUE;
- }
- }
- else if (ResponseHeader->CallId != RequestHeader->CallId)
- {
- p("Fatal: Sent Call Id %u but received answer for Call Id %u\n",
- (uint32_t)LE32(RequestHeader->CallId),
- (uint32_t)LE32(ResponseHeader->CallId)
- );
-
- status = !0;
- }
-
- return status;
-}
-
-/*
- * Initializes an RPC request header as needed for KMS, i.e. packet always fits in one fragment.
- * size cannot be greater than fragment length negotiated during RPC bind.
- */
-static void createRpcRequestHeader(RPC_HEADER* RequestHeader, BYTE packetType, WORD size)
-{
- RequestHeader->PacketType = packetType;
- RequestHeader->PacketFlags = RPC_PF_FIRST | RPC_PF_LAST;
- RequestHeader->VersionMajor = 5;
- RequestHeader->VersionMinor = 0;
- RequestHeader->AuthLength = 0;
- RequestHeader->DataRepresentation = BE32(0x10000000); // Little endian, ASCII charset, IEEE floating point
- RequestHeader->CallId = LE32(CallId);
- RequestHeader->FragLength = LE16(size);
-}
-
-
-/*
- * Sends a KMS request via RPC and receives a response.
- * Parameters are raw (encrypted) reqeuests / responses.
- * Returns 0 on success.
- */
-RpcStatus rpcSendRequest(const RpcCtx sock, const BYTE *const KmsRequest, const size_t requestSize, BYTE **KmsResponse, size_t *const responseSize)
-{
- #define MAX_EXCESS_BYTES 16
- RPC_HEADER *RequestHeader, ResponseHeader;
- RPC_REQUEST64 *RpcRequest;
- RPC_RESPONSE64 _Response;
- int status = 0;
- int_fast8_t useNdr64 = UseRpcNDR64 && firstPacketSent;
- size_t size = sizeof(RPC_HEADER) + (useNdr64 ? sizeof(RPC_REQUEST64) : sizeof(RPC_REQUEST)) + requestSize;
- size_t responseSize2;
-
- *KmsResponse = NULL;
-
- BYTE *_Request = (BYTE*)vlmcsd_malloc(size);
-
- RequestHeader = (RPC_HEADER*)_Request;
- RpcRequest = (RPC_REQUEST64*)(_Request + sizeof(RPC_HEADER));
-
- createRpcRequestHeader(RequestHeader, RPC_PT_REQUEST, size);
-
- // Increment CallId for next Request
- CallId++;
-
- RpcRequest->Opnum = 0;
-
- if (useNdr64)
- {
- RpcRequest->ContextId = LE16(1); // We negotiate NDR64 always as context 1
- RpcRequest->AllocHint = LE32(requestSize + sizeof(RpcRequest->Ndr64));
- RpcRequest->Ndr64.DataLength = LE64((uint64_t)requestSize);
- RpcRequest->Ndr64.DataSizeIs = LE64((uint64_t)requestSize);
- memcpy(RpcRequest->Ndr64.Data, KmsRequest, requestSize);
- }
- else
- {
- RpcRequest->ContextId = 0; // We negotiate NDR32 always as context 0
- RpcRequest->AllocHint = LE32(requestSize + sizeof(RpcRequest->Ndr));
- RpcRequest->Ndr.DataLength = LE32(requestSize);
- RpcRequest->Ndr.DataSizeIs = LE32(requestSize);
- memcpy(RpcRequest->Ndr.Data, KmsRequest, requestSize);
- }
-
- for(;;)
- {
- int bytesread;
-
- if (!_send(sock, _Request, size))
- {
- errorout("\nFatal: Could not send RPC request\n");
- status = !0;
- break;
- }
-
- if (!_recv(sock, &ResponseHeader, sizeof(RPC_HEADER)))
- {
- errorout("\nFatal: No RPC response received from server\n");
- status = !0;
- break;
- }
-
- if ((status = checkRpcResponseHeader(&ResponseHeader, RequestHeader, RPC_PT_RESPONSE, &errorout))) break;
-
- size = useNdr64 ? sizeof(RPC_RESPONSE64) : sizeof(RPC_RESPONSE);
-
- if (size > LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader))
- size = LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader);
-
- if (!_recv(sock, &_Response, size))
- {
- errorout("\nFatal: RPC response is incomplete\n");
- status = !0;
- break;
- }
-
- if (_Response.CancelCount != 0)
- {
- errorout("\nFatal: RPC response cancel count is not 0\n");
- status = !0;
- }
-
- if (_Response.ContextId != (useNdr64 ? LE16(1) : 0))
- {
- errorout("\nFatal: RPC response context id %u is not bound\n", (unsigned int)LE16(_Response.ContextId));
- status = !0;
- }
-
- int_fast8_t sizesMatch;
-
- if (useNdr64)
- {
- *responseSize = (size_t)LE64(_Response.Ndr64.DataLength);
- responseSize2 = (size_t)LE64(_Response.Ndr64.DataSizeIs);
-
- if (!*responseSize || !_Response.Ndr64.DataSizeMax)
- {
- status = (int)LE32(_Response.Ndr64.status);
- break;
- }
-
- sizesMatch = (size_t)LE64(_Response.Ndr64.DataLength) == responseSize2;
- }
- else
- {
- *responseSize = (size_t)LE32(_Response.Ndr.DataLength);
- responseSize2 = (size_t)LE32(_Response.Ndr.DataSizeIs);
-
- if (!*responseSize || !_Response.Ndr.DataSizeMax)
- {
- status = (int)LE32(_Response.Ndr.status);
- break;
- }
-
- sizesMatch = (size_t)LE32(_Response.Ndr.DataLength) == responseSize2;
- }
-
- if (!sizesMatch)
- {
- errorout("\nFatal: NDR data length (%u) does not match NDR data size (%u)\n",
- (uint32_t)*responseSize,
- (uint32_t)LE32(_Response.Ndr.DataSizeIs)
- );
-
- status = !0;
- }
-
- *KmsResponse = (BYTE*)vlmcsd_malloc(*responseSize + MAX_EXCESS_BYTES);
-
- // If RPC stub is too short, assume missing bytes are zero (same ill behavior as MS RPC)
- memset(*KmsResponse, 0, *responseSize + MAX_EXCESS_BYTES);
-
- // Read up to 16 bytes more than bytes expected to detect faulty KMS emulators
- if ((bytesread = recv(sock, (char*)*KmsResponse, *responseSize + MAX_EXCESS_BYTES, 0)) < (int)*responseSize)
- {
- errorout("\nFatal: No or incomplete KMS response received. Required %u bytes but only got %i\n",
- (uint32_t)*responseSize,
- (int32_t)(bytesread < 0 ? 0 : bytesread)
- );
-
- status = !0;
- break;
- }
-
- DWORD *pReturnCode;
-
- size_t len = *responseSize + (useNdr64 ? sizeof(_Response.Ndr64) : sizeof(_Response.Ndr)) + sizeof(*pReturnCode);
- size_t pad = ((~len & 3) + 1) & 3;
-
- if (len + pad != LE32(_Response.AllocHint))
- {
- errorout("\nWarning: RPC stub size is %u, should be %u (probably incorrect padding)\n", (uint32_t)LE32(_Response.AllocHint), (uint32_t)(len + pad));
- }
- else
- {
- size_t i;
- for (i = 0; i < pad; i++)
- {
- if (*(*KmsResponse + *responseSize + sizeof(*pReturnCode) + i))
- {
- errorout("\nWarning: RPC stub data not padded to zeros according to Microsoft standard\n");
- break;
- }
- }
- }
-
- pReturnCode = (DWORD*)(*KmsResponse + *responseSize + pad);
- status = LE32(UA32(pReturnCode));
-
- if (status) errorout("\nWarning: RPC stub data reported Error %u\n", (uint32_t)status);
-
- break;
- }
-
- free(_Request);
- firstPacketSent = TRUE;
- return status;
- #undef MAX_EXCESS_BYTES
-}
-
-
-static int_fast8_t IsNullGuid(BYTE* guidPtr)
-{
- int_fast8_t i;
-
- for (i = 0; i < 16; i++)
- {
- if (guidPtr[i]) return FALSE;
- }
-
- return TRUE;
-}
-
-/*
- * Perform RPC client bind. Accepts a connected client socket.
- * Returns 0 on success. RPC binding is required before any payload can be
- * exchanged. It negotiates about protocol details.
- */
-RpcStatus rpcBindOrAlterClientContext(const RpcCtx sock, BYTE packetType, const int_fast8_t verbose)
-{
- RPC_HEADER *RequestHeader, ResponseHeader;
- RPC_BIND_REQUEST *bindRequest;
- RPC_BIND_RESPONSE *bindResponse;
- int status;
- WORD ctxItems = 1 + (packetType == RPC_PT_BIND_REQ ? UseRpcNDR64 + UseRpcBTFN : 0);
- size_t rpcBindSize = (sizeof(RPC_HEADER) + sizeof(RPC_BIND_REQUEST) + (ctxItems - 1) * sizeof(bindRequest->CtxItems[0]));
- WORD ctxIndex = 0;
- WORD i;
- WORD CtxBTFN = (WORD)~0, CtxNDR64 = (WORD)~0;
- BYTE _Request[rpcBindSize];
-
- RequestHeader = (RPC_HEADER*)_Request;
- bindRequest = (RPC_BIND_REQUEST* )(_Request + sizeof(RPC_HEADER));
-
- createRpcRequestHeader(RequestHeader, packetType, rpcBindSize);
- RequestHeader->PacketFlags |= UseMultiplexedRpc ? RPC_PF_MULTIPLEX : 0;
-
- bindRequest->AssocGroup = 0;
- bindRequest->MaxRecvFrag = bindRequest->MaxXmitFrag = LE16(5840);
- bindRequest->NumCtxItems = LE32(ctxItems);
-
- // data that is identical in all Ctx items
- for (i = 0; i < ctxItems; i++)
- {
- bindRequest->CtxItems[i].ContextId = LE16(i);
- bindRequest->CtxItems[i].InterfaceVerMajor = LE16(1);
- bindRequest->CtxItems[i].InterfaceVerMinor = 0;
- bindRequest->CtxItems[i].NumTransItems = LE16(1);
- bindRequest->CtxItems[i].SyntaxVersion = i ? LE32(1) : LE32(2);
-
- memcpy(&bindRequest->CtxItems[i].InterfaceUUID, InterfaceUuid, sizeof(GUID));
- }
-
- memcpy(&bindRequest->CtxItems[0].TransferSyntax, TransferSyntaxNDR32, sizeof(GUID));
-
- if (UseRpcNDR64 && packetType == RPC_PT_BIND_REQ)
- {
- memcpy(&bindRequest->CtxItems[++ctxIndex].TransferSyntax, TransferSyntaxNDR64, sizeof(GUID));
- CtxNDR64 = ctxIndex;
- }
-
- if (UseRpcBTFN && packetType == RPC_PT_BIND_REQ)
- {
- memcpy(&bindRequest->CtxItems[++ctxIndex].TransferSyntax, BindTimeFeatureNegotiation, sizeof(GUID));
- CtxBTFN = ctxIndex;
- }
-
- if (!_send(sock, _Request, rpcBindSize))
- {
- errorout("\nFatal: Sending RPC bind request failed\n");
- return !0;
- }
-
- if (!_recv(sock, &ResponseHeader, sizeof(RPC_HEADER)))
- {
- errorout("\nFatal: Did not receive a response from server\n");
- return !0;
- }
-
- if ((status = checkRpcResponseHeader
- (
- &ResponseHeader,
- RequestHeader,
- packetType == RPC_PT_BIND_REQ ? RPC_PT_BIND_ACK : RPC_PT_ALTERCONTEXT_ACK,
- &errorout
- )))
- {
- return status;
- }
-
- bindResponse = (RPC_BIND_RESPONSE*)vlmcsd_malloc(LE16(ResponseHeader.FragLength) - sizeof(RPC_HEADER));
- BYTE* bindResponseBytePtr = (BYTE*)bindResponse;
-
- if (!_recv(sock, bindResponse, LE16(ResponseHeader.FragLength) - sizeof(RPC_HEADER)))
- {
- errorout("\nFatal: Incomplete RPC bind acknowledgement received\n");
- free(bindResponseBytePtr);
- return !0;
- }
- else
- {
- /*
- * checking, whether a bind or alter context response is as expected.
- * This check is very strict and checks whether a KMS emulator behaves exactly the same way
- * as Microsoft's RPC does.
- */
- status = 0;
-
- if (bindResponse->SecondaryAddressLength < LE16(3))
- bindResponse = (RPC_BIND_RESPONSE*)(bindResponseBytePtr - 4);
-
- if (bindResponse->NumResults != bindRequest->NumCtxItems)
- {
- errorout("\nFatal: Expected %u CTX items but got %u\n",
- (uint32_t)LE32(bindRequest->NumCtxItems),
- (uint32_t)LE32(bindResponse->NumResults)
- );
-
- status = !0;
- }
-
- for (i = 0; i < ctxItems; i++)
- {
- const char* transferSyntaxName =
- i == CtxBTFN ? "BTFN" : i == CtxNDR64 ? "NDR64" : "NDR32";
-
- if (bindResponse->Results[i].AckResult == RPC_BIND_NACK) // transfer syntax was declined
- {
- if (!IsNullGuid((BYTE*)&bindResponse->Results[i].TransferSyntax))
- {
- errorout(
- "\nWarning: Rejected transfer syntax %s did not return NULL Guid\n",
- transferSyntaxName
- );
- }
-
- if (bindResponse->Results[i].SyntaxVersion)
- {
- errorout(
- "\nWarning: Rejected transfer syntax %s did not return syntax version 0 but %u\n",
- transferSyntaxName,
- LE32(bindResponse->Results[i].SyntaxVersion)
- );
- }
-
- if (bindResponse->Results[i].AckReason == RPC_ABSTRACTSYNTAX_UNSUPPORTED)
- {
- errorout(
- "\nWarning: Transfer syntax %s does not support KMS activation\n",
- transferSyntaxName
- );
- }
- else if (bindResponse->Results[i].AckReason != RPC_SYNTAX_UNSUPPORTED)
- {
- errorout(
- "\nWarning: Rejected transfer syntax %s did not return ack reason RPC_SYNTAX_UNSUPPORTED\n",
- transferSyntaxName
- );
- }
-
- continue;
- }
-
- if (i == CtxBTFN) // BTFN
- {
- if (bindResponse->Results[i].AckResult != RPC_BIND_ACK)
- {
- errorout("\nWarning: BTFN did not respond with RPC_BIND_ACK or RPC_BIND_NACK\n");
- }
-
- if (bindResponse->Results[i].AckReason != LE16(3))
- {
- errorout("\nWarning: BTFN did not return expected feature mask 0x3 but 0x%X\n", (unsigned int)LE16(bindResponse->Results[i].AckReason));
- }
-
- if (verbose) printf("... BTFN ");
- RpcFlags.HasBTFN = TRUE;
-
- continue;
- }
-
- // NDR32 or NDR64 Ctx
- if (bindResponse->Results[i].AckResult != RPC_BIND_ACCEPT)
- {
- errorout(
- "\nFatal: transfer syntax %s returned an invalid status, neither RPC_BIND_ACCEPT nor RPC_BIND_NACK\n",
- transferSyntaxName
- );
-
- status = !0;
- }
-
- if (!IsEqualGUID(&bindResponse->Results[i].TransferSyntax, &bindRequest->CtxItems[i].TransferSyntax))
- {
- errorout(
- "\nFatal: Transfer syntax of RPC bind request and response does not match\n"
- );
-
- status = !0;
- }
-
- if (bindResponse->Results[i].SyntaxVersion != bindRequest->CtxItems[i].SyntaxVersion)
- {
- errorout("\nFatal: Expected transfer syntax version %u for %s but got %u\n",
- (uint32_t)LE32(bindRequest->CtxItems[0].SyntaxVersion),
- transferSyntaxName,
- (uint32_t)LE32(bindResponse->Results[0].SyntaxVersion)
- );
-
- status = !0;
- }
-
- // The ack reason field is actually undefined here but Microsoft sets this to 0
- if (bindResponse->Results[i].AckReason != 0)
- {
- errorout(
- "\nWarning: Ack reason should be 0 but is %u\n",
- LE16(bindResponse->Results[i].AckReason)
- );
- }
-
- if (!status)
- {
- if (i == CtxNDR64)
- {
- RpcFlags.HasNDR64 = TRUE;
- if (verbose) printf("... NDR64 ");
- }
- if (!i)
- {
- RpcFlags.HasNDR32 = TRUE;
- if (verbose) printf("... NDR32 ");
- }
-
- }
- }
- }
-
- free(bindResponseBytePtr);
-
- if (!RpcFlags.HasNDR64 && !RpcFlags.HasNDR32)
- {
- errorout("\nFatal: Could neither negotiate NDR32 nor NDR64 with the RPC server\n");
- status = !0;
- }
-
- return status;
-}
-
-RpcStatus rpcBindClient(const RpcCtx sock, const int_fast8_t verbose)
-{
- firstPacketSent = FALSE;
- RpcFlags.mask = 0;
-
- RpcStatus status =
- rpcBindOrAlterClientContext(sock, RPC_PT_BIND_REQ, verbose);
-
- if (status) return status;
-
- if (!RpcFlags.HasNDR32)
- status = rpcBindOrAlterClientContext(sock, RPC_PT_ALTERCONTEXT_REQ, verbose);
-
- return status;
-}
-
-#endif // USE_MSRPC
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#if !defined(_CRYPTO_OPENSSL) && !defined(_CRYPTO_POLARSSL) && !defined(_CRYPTO_WINDOWS)
-#include "crypto_internal.h"
-#include "endian.h"
-
-#define F0(x, y, z) ( ((x) & (y)) | (~(x) & (z)) )
-#define F1(x, y, z) ( ((x) & (y)) | ((x) & (z)) | ((y) & (z)) )
-
-#define SI1(x) ( ROR32(x, 2 ) ^ ROR32(x, 13) ^ ROR32(x, 22) )
-#define SI2(x) ( ROR32(x, 6 ) ^ ROR32(x, 11) ^ ROR32(x, 25) )
-#define SI3(x) ( ROR32(x, 7 ) ^ ROR32(x, 18) ^ ((x) >> 3 ) )
-#define SI4(x) ( ROR32(x, 17) ^ ROR32(x, 19) ^ ((x) >> 10) )
-
-static const DWORD k[] = {
- 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1,
- 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
- 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786,
- 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
- 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147,
- 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
- 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B,
- 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
- 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A,
- 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
- 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
-};
-
-
-static void Sha256Init(Sha256Ctx *Ctx)
-{
- Ctx->State[0] = 0x6A09E667;
- Ctx->State[1] = 0xBB67AE85;
- Ctx->State[2] = 0x3C6EF372;
- Ctx->State[3] = 0xA54FF53A;
- Ctx->State[4] = 0x510E527F;
- Ctx->State[5] = 0x9B05688C;
- Ctx->State[6] = 0x1F83D9AB;
- Ctx->State[7] = 0x5BE0CD19;
- Ctx->Len = 0;
-}
-
-
-static void Sha256ProcessBlock(Sha256Ctx *Ctx, BYTE *block)
-{
- unsigned int i;
- DWORD w[64], temp1, temp2;
- DWORD a = Ctx->State[0];
- DWORD b = Ctx->State[1];
- DWORD c = Ctx->State[2];
- DWORD d = Ctx->State[3];
- DWORD e = Ctx->State[4];
- DWORD f = Ctx->State[5];
- DWORD g = Ctx->State[6];
- DWORD h = Ctx->State[7];
-
- for (i = 0; i < 16; i++)
- //w[ i ] = GET_UAA32BE(block, i);
- w[i] = BE32(((DWORD*)block)[i]);
-
- for (i = 16; i < 64; i++)
- w[ i ] = SI4(w[ i - 2 ]) + w[ i - 7 ] + SI3(w[ i - 15 ]) + w[ i - 16 ];
-
- for (i = 0; i < 64; i++)
- {
- temp1 = h + SI2(e) + F0(e, f, g) + k[ i ] + w[ i ];
- temp2 = SI1(a) + F1(a, b, c);
-
- h = g;
- g = f;
- f = e;
- e = d + temp1;
- d = c;
- c = b;
- b = a;
- a = temp1 + temp2;
- }
-
- Ctx->State[0] += a;
- Ctx->State[1] += b;
- Ctx->State[2] += c;
- Ctx->State[3] += d;
- Ctx->State[4] += e;
- Ctx->State[5] += f;
- Ctx->State[6] += g;
- Ctx->State[7] += h;
-}
-
-
-static void Sha256Update(Sha256Ctx *Ctx, BYTE *data, size_t len)
-{
- unsigned int b_len = Ctx->Len & 63,
- r_len = (b_len ^ 63) + 1;
-
- Ctx->Len += len;
-
- if ( len < r_len )
- {
- memcpy(Ctx->Buffer + b_len, data, len);
- return;
- }
-
- if ( r_len < 64 )
- {
- memcpy(Ctx->Buffer + b_len, data, r_len);
- len -= r_len;
- data += r_len;
- Sha256ProcessBlock(Ctx, Ctx->Buffer);
- }
-
- for (; len >= 64; len -= 64, data += 64)
- Sha256ProcessBlock(Ctx, data);
-
- if ( len ) memcpy(Ctx->Buffer, data, len);
-}
-
-
-static void Sha256Finish(Sha256Ctx *Ctx, BYTE *hash)
-{
- unsigned int i, b_len = Ctx->Len & 63;
-
- Ctx->Buffer[ b_len ] = 0x80;
- if ( b_len ^ 63 ) memset(Ctx->Buffer + b_len + 1, 0, b_len ^ 63);
-
- if ( b_len >= 56 )
- {
- Sha256ProcessBlock(Ctx, Ctx->Buffer);
- memset(Ctx->Buffer, 0, 56);
- }
-
- //PUT_UAA64BE(Ctx->Buffer, (unsigned long long)(Ctx->Len * 8), 7);
- ((uint64_t*)Ctx->Buffer)[7] = BE64((uint64_t)Ctx->Len << 3);
- Sha256ProcessBlock(Ctx, Ctx->Buffer);
-
- for (i = 0; i < 8; i++)
- //PUT_UAA32BE(hash, Ctx->State[i], i);
- ((DWORD*)hash)[i] = BE32(Ctx->State[i]);
-
-}
-
-
-void Sha256(BYTE *data, size_t len, BYTE *hash)
-{
- Sha256Ctx Ctx;
-
- Sha256Init(&Ctx);
- Sha256Update(&Ctx, data, len);
- Sha256Finish(&Ctx, hash);
-}
-
-
-static void _Sha256HmacInit(Sha256HmacCtx *Ctx, BYTE *key, size_t klen)
-{
- BYTE IPad[64];
- unsigned int i;
-
- memset(IPad, 0x36, sizeof(IPad));
- memset(Ctx->OPad, 0x5C, sizeof(Ctx->OPad));
-
- if ( klen > 64 )
- {
- BYTE *temp = (BYTE*)alloca(32);
- Sha256(key, klen, temp);
- klen = 32;
- key = temp;
- }
-
- for (i = 0; i < klen; i++)
- {
- IPad[ i ] ^= key[ i ];
- Ctx->OPad[ i ] ^= key[ i ];
- }
-
- Sha256Init(&Ctx->ShaCtx);
- Sha256Update(&Ctx->ShaCtx, IPad, sizeof(IPad));
-}
-
-
-static void _Sha256HmacUpdate(Sha256HmacCtx *Ctx, BYTE *data, size_t len)
-{
- Sha256Update(&Ctx->ShaCtx, data, len);
-}
-
-
-static void _Sha256HmacFinish(Sha256HmacCtx *Ctx, BYTE *hmac)
-{
- BYTE temp[32];
-
- Sha256Finish(&Ctx->ShaCtx, temp);
- Sha256Init(&Ctx->ShaCtx);
- Sha256Update(&Ctx->ShaCtx, Ctx->OPad, sizeof(Ctx->OPad));
- Sha256Update(&Ctx->ShaCtx, temp, sizeof(temp));
- Sha256Finish(&Ctx->ShaCtx, hmac);
-}
-
-
-
-int_fast8_t Sha256Hmac(BYTE* key, BYTE* restrict data, DWORD len, BYTE* restrict hmac)
-{
- Sha256HmacCtx Ctx;
- _Sha256HmacInit(&Ctx, key, 16);
- _Sha256HmacUpdate(&Ctx, data, len);
- _Sha256HmacFinish(&Ctx, hmac);
- return TRUE;
-}
-
-
-#endif // No external Crypto
-
diff --git a/vlmcsdmulti.1.html b/vlmcsdmulti.1.html
index d1d0cc8..37785c6 100644
--- a/vlmcsdmulti.1.html
+++ b/vlmcsdmulti.1.html
@@ -1,5 +1,5 @@
-
+
diff --git a/vlmcsdmulti.1.pdf b/vlmcsdmulti.1.pdf
index ccb297e..956605f 100644
Binary files a/vlmcsdmulti.1.pdf and b/vlmcsdmulti.1.pdf differ
diff --git a/vlmcsdmulti_all.c b/vlmcsdmulti_all.c
deleted file mode 100644
index 40fe62b..0000000
--- a/vlmcsdmulti_all.c
+++ /dev/null
@@ -1,8274 +0,0 @@
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#if defined(USE_MSRPC) && !defined(_WIN32) && !defined(__CYGWIN__)
-#error Microsoft RPC is only available on Windows and Cygwin
-#endif
-
-#if defined(NO_SOCKETS) && defined(USE_MSRPC)
-#error Cannot use inetd mode with Microsoft RPC
-#endif
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include
-#include
-#include
-#include
-#include
-
-#ifndef _WIN32
-#include
-#include
-#include
-
-#if !defined(NO_LIMIT) && !__minix__
-#include
-#if !__ANDROID__
-#include
-#else // __ANDROID__
-#include
-#endif // __ANDROID__
-#endif // !defined(NO_LIMIT) && !__minix__
-
-#include
-#include
-#include
-#include
-#include
-#endif // !_WIN32
-
-#if __APPLE__
-#include
-#endif // __APPLE__
-
-#if __linux__ && defined(USE_AUXV)
-#include
-#endif
-
-#if __FreeBSD__
-#include
-#endif
-
-#include "vlmcsd.h"
-#include "endian.h"
-#include "shared_globals.h"
-#include "output.h"
-#ifndef USE_MSRPC
-#include "network.h"
-#else // USE_MSRPC
-#include "msrpc-server.h"
-#endif // USE_MSRPC
-#include "ntservice.h"
-#include "helpers.h"
-
-
-static const char* const optstring = "N:B:m:t:w:0:3:H:A:R:u:g:L:p:i:P:l:r:U:W:C:SsfeDd46VvIdqkZ";
-
-#if !defined(NO_SOCKETS)
-#if !defined(USE_MSRPC)
-static uint_fast8_t maxsockets = 0;
-static int_fast8_t haveIPv6Stack = 0;
-static int_fast8_t haveIPv4Stack = 0;
-static int_fast8_t v6required = 0;
-static int_fast8_t v4required = 0;
-#endif // !defined(USE_MSRPC)
-#endif // !defined(NO_SOCKETS)
-
-#ifdef _NTSERVICE
-static int_fast8_t installService = 0;
-static const char *restrict ServiceUser = NULL;
-static const char *restrict ServicePassword = "";
-#endif
-
-#ifndef NO_PID_FILE
-static const char *fn_pid = NULL;
-#endif
-
-#ifndef NO_INI_FILE
-
-#ifdef INI_FILE
-static const char *fn_ini = INI_FILE;
-#else // !INI_FILE
-static const char *fn_ini = NULL;
-#endif // !INI_FILE
-
-static const char* IniFileErrorMessage = "";
-char* IniFileErrorBuffer = NULL;
-#define INIFILE_ERROR_BUFFERSIZE 256
-
-static IniFileParameter_t IniFileParameterList[] =
-{
-# ifndef NO_RANDOM_EPID
- { "RandomizationLevel", INI_PARAM_RANDOMIZATION_LEVEL },
- { "LCID", INI_PARAM_LCID },
-# endif // NO_RANDOM_EPID
-# ifdef USE_MSRPC
- { "Port", INI_PARAM_PORT },
-# endif // USE_MSRPC
-# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- { "Listen", INI_PARAM_LISTEN },
-# if !defined(NO_LIMIT) && !__minix__
- { "MaxWorkers", INI_PARAM_MAX_WORKERS },
-# endif // !defined(NO_LIMIT) && !__minix__
-# endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-# if !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC) & !defined(USE_MSRPC)
- { "ConnectionTimeout", INI_PARAM_CONNECTION_TIMEOUT },
-# endif // !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC) & !defined(USE_MSRPC)
-# ifndef USE_MSRPC
- { "DisconnectClientsImmediately", INI_PARAM_DISCONNECT_IMMEDIATELY },
- { "UseNDR64", INI_PARAM_RPC_NDR64 },
- { "UseBTFN", INI_PARAM_RPC_BTFN },
-# endif // USE_MSRPC
-# ifndef NO_PID_FILE
- { "PIDFile", INI_PARAM_PID_FILE },
-# endif // NO_PID_FILE
-# ifndef NO_LOG
- { "LogFile", INI_PARAM_LOG_FILE },
-# ifndef NO_VERBOSE_LOG
- { "LogVerbose", INI_PARAM_LOG_VERBOSE },
-# endif // NO_VERBOSE_LOG
-# endif // NO_LOG
-# ifndef NO_CUSTOM_INTERVALS
- {"ActivationInterval", INI_PARAM_ACTIVATION_INTERVAL },
- {"RenewalInterval", INI_PARAM_RENEWAL_INTERVAL },
-# endif // NO_CUSTOM_INTERVALS
-# if !defined(NO_USER_SWITCH) && !defined(_WIN32)
- { "user", INI_PARAM_UID },
- { "group", INI_PARAM_GID},
-# endif // !defined(NO_USER_SWITCH) && !defined(_WIN32)
-};
-
-#endif // NO_INI_FILE
-
-
-#if !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-
-#if !defined(USE_THREADS) && !defined(CYGWIN) && !defined(USE_MSRPC)
-static int shmid = -1;
-#endif
-
-#if __ANDROID__ && !defined(USE_THREADS) // Bionic does not wrap these syscalls (willingly because Google fears, developers don't know how to use it)
-
-#ifdef __NR_shmget
-static int shmget(key_t key, size_t size, int shmflg)
-{
- return syscall(__NR_shmget, key, size, shmflg);
-}
-#endif // __NR_shmget
-
-#ifdef __NR_shmat
-static void *shmat(int shmid, const void *shmaddr, int shmflg)
-{
- return (void *)syscall(__NR_shmat, shmid, shmaddr, shmflg);
-}
-#endif // __NR_shmat
-
-#ifdef __NR_shmdt
-static int shmdt(const void *shmaddr)
-{
- return syscall(__NR_shmdt, shmaddr);
-}
-#endif // __NR_shmdt
-
-#ifdef __NR_shmctl
-static int shmctl(int shmid, int cmd, /*struct shmid_ds*/void *buf)
-{
- return syscall(__NR_shmctl, shmid, cmd, buf);
-}
-#endif // __NR_shmctl
-
-#endif // __ANDROID__ && !defined(USE_THREADS)
-
-#endif // !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-
-#ifndef NO_USER_SWITCH
-#ifndef _WIN32
-
-static const char *uname = NULL, *gname = NULL;
-static gid_t gid = INVALID_GID;
-static uid_t uid = INVALID_UID;
-
-// Get Numeric id of user/group
-static char GetNumericId(gid_t *restrict id, const char *const c)
-{
- char* endptr;
- gid_t temp;
-
- temp = (gid_t)strtoll(c, &endptr, 10);
-
- if (!*endptr) *id = temp;
-
- return *endptr;
-}
-
-
-// Get group id from option argument
-static char GetGid()
-{
- struct group *g;
-
- if ((g = getgrnam(optarg)))
- gid = g->gr_gid;
- else
- return GetNumericId(&gid, optarg);
-
- return 0;
-}
-
-
-// Get user id from option argument
-static char GetUid()
-{
- struct passwd *u;
-
- ////PORTABILITY: Assumes uid_t and gid_t are of same size (shouldn't be a problem)
- if ((u = getpwnam(optarg)))
- uid = u->pw_uid;
- else
- return GetNumericId((gid_t*)&uid, optarg);
-
- return 0;
-}
-#endif // _WIN32
-#endif //NO_USER_SWITCH
-
-#ifdef NO_HELP
-static __noreturn void usage()
-{
- printerrorf("Incorrect parameters\n\n");
- exit(!0);
-}
-#else // HELP
-
-
-static __noreturn void usage()
-{
- printerrorf("vlmcsd %s\n"
- "\nUsage:\n"
- " %s [ options ]\n\n"
- "Where:\n"
- #ifndef NO_CL_PIDS
- " -w always use for Windows\n"
- " -0 always use for Office2010\n"
- " -3 always use for Office2013\n"
- " -H always use hardware Id \n"
- #endif // NO_CL_PIDS
- #if !defined(_WIN32) && !defined(NO_USER_SWITCH)
- " -u set uid to \n"
- " -g set gid to \n"
- #endif // !defined(_WIN32) && !defined(NO_USER_SWITCH)
- #ifndef NO_RANDOM_EPID
- " -r 0|1|2\t\tset ePID randomization level (default 1)\n"
- " -C \t\tuse fixed in random ePIDs\n"
- #endif // NO_RANDOM_EPID
- #ifndef NO_SOCKETS
- #ifndef USE_MSRPC
- " -4\t\t\tuse IPv4\n"
- " -6\t\t\tuse IPv6\n"
- " -L [:]\tlisten on IP address with optional \n"
- " -P \t\tset TCP port for subsequent -L statements (default 1688)\n"
- #else // USE_MSRPC
- " -P \t\tuse TCP port (default 1688)\n"
- #endif // USE_MSRPC
- #if !defined(NO_LIMIT) && !__minix__
- " -m \t\tHandle max. simultaneously (default no limit)\n"
- #endif // !defined(NO_LIMIT) && !__minix__
- #ifdef _NTSERVICE
- " -s install vlmcsd as an NT service. Ignores -e"
- #ifndef _WIN32
- ", -f and -D"
- #endif // _WIN32
- "\n"
- " -S remove vlmcsd service. Ignores all other options\n"
- " -U run NT service as . Must be used with -s\n"
- " -W optional for -U. Must be used with -s\n"
- #endif // _NTSERVICE
- #ifndef NO_LOG
- " -e log to stdout\n"
- #endif // NO_LOG
- #ifndef _WIN32 //
- " -D run in foreground\n"
- " -f run in foreground"
- #ifndef NO_LOG
- " and log to stdout"
- #endif // NO_LOG
- "\n"
- #endif // _WIN32
- #endif // NO_SOCKETS
- #ifndef USE_MSRPC
- #if !defined(NO_TIMEOUT) && !__minix__
- " -t \t\tdisconnect clients after of inactivity (default 30)\n"
- #endif // !defined(NO_TIMEOUT) && !__minix__
- " -d\t\t\tdisconnect clients after each request\n"
- " -k\t\t\tdon't disconnect clients after each request (default)\n"
- " -N0, -N1\t\tdisable/enable NDR64\n"
- " -B0, -B1\t\tdisable/enable bind time feature negotiation\n"
- #endif // USE_MSRPC
- #ifndef NO_PID_FILE
- " -p write pid to \n"
- #endif // NO_PID_FILE
- #ifndef NO_INI_FILE
- " -i \t\tuse config file \n"
- #endif // NO_INI_FILE
- #ifndef NO_CUSTOM_INTERVALS
- " -R renew activation every (default 1w)\n"
- " -A retry activation every (default 2h)\n"
- #endif // NO_CUSTOM_INTERVALS
- #ifndef NO_LOG
- #ifndef _WIN32
- " -l syslog log to syslog\n"
- #endif // _WIN32
- " -l log to \n"
- #ifndef NO_VERBOSE_LOG
- " -v\t\t\tlog verbose\n"
- " -q\t\t\tdon't log verbose (default)\n"
- #endif // NO_VERBOSE_LOG
- #endif // NO_LOG
- " -V display version information and exit"
- "\n",
- Version, global_argv[0]);
-
- exit(!0);
-}
-#endif // HELP
-
-
-#ifndef NO_CUSTOM_INTERVALS
-
-// Convert time span strings (e.g. "2h", "5w") to minutes
-__pure static DWORD timeSpanString2Minutes(const char *const restrict argument)
-{
- char *unitId;
-
- long long val = strtoll(argument, &unitId, 10);
-
- switch(toupper((int)*unitId))
- {
- case 0:
- case 'M':
- break;
- case 'H':
- val *= 60;
- break;
- case 'D':
- val *= 60 * 24;
- break;
- case 'W':
- val *= 60 * 24 * 7;
- break;
- case 'S':
- val /= 60;
- break;
- default:
- return 0;
- }
-
- if (val < 1) val = 1;
- if (val > UINT_MAX) val = UINT_MAX;
-
- return (DWORD)val;
-}
-
-
-#ifndef NO_INI_FILE
-__pure static BOOL getTimeSpanFromIniFile(DWORD* result, const char *const restrict argument)
-{
- DWORD val = timeSpanString2Minutes(argument);
- if (!val)
- {
- IniFileErrorMessage = "Incorrect time span.";
- return FALSE;
- }
-
- *result = val;
- return TRUE;
-}
-#endif // NO_INI_FILE
-
-
-__pure static DWORD getTimeSpanFromCommandLine(const char *const restrict optarg, const char optchar)
-{
- long long val = timeSpanString2Minutes(optarg);
-
- if (!val)
- {
- printerrorf("Fatal: No valid time span specified in option -%c.\n", optchar);
- exit (!0);
- }
-
- return (DWORD)val;
-}
-
-#endif // NO_CUSTOM_INTERVALS
-
-
-#ifndef NO_INI_FILE
-static void ignoreIniFileParameter(uint_fast8_t iniFileParameterId)
-{
- uint_fast8_t i;
-
- for (i = 0; i < _countof(IniFileParameterList); i++)
- {
- if (IniFileParameterList[i].Id != iniFileParameterId) continue;
- IniFileParameterList[i].Id = 0;
- break;
- }
-}
-#else // NO_INI_FILE
-#define ignoreIniFileParameter(x)
-#endif // NO_INI_FILE
-
-
-#ifndef NO_INI_FILE
-static BOOL getIniFileArgumentBool(int_fast8_t *result, const char *const argument)
-{
- IniFileErrorMessage = "Argument must be true/on/yes/1 or false/off/no/0";
- return getArgumentBool(result, argument);
-}
-
-
-static BOOL getIniFileArgumentInt(unsigned int *result, const char *const argument, const unsigned int min, const unsigned int max)
-{
- unsigned int tempResult;
-
- if (!stringToInt(argument, min, max, &tempResult))
- {
- snprintf(IniFileErrorBuffer, INIFILE_ERROR_BUFFERSIZE, "Must be integer between %u and %u", min, max);
- IniFileErrorMessage = IniFileErrorBuffer;
- return FALSE;
- }
-
- *result = tempResult;
- return TRUE;
-}
-
-
-static char* allocateStringArgument(const char *const argument)
-{
- char* result = (char*)vlmcsd_malloc(strlen(argument) + 1);
- strcpy(result, argument);
- return result;
-}
-
-
-static BOOL setIniFileParameter(uint_fast8_t id, const char *const iniarg)
-{
- unsigned int result;
- BOOL success = TRUE;
-
- switch(id)
- {
-# if !defined(NO_USER_SWITCH) && !defined(_WIN32)
-
- case INI_PARAM_GID:
- {
- struct group *g;
- IniFileErrorMessage = "Invalid group id or name";
- if (!(gname = allocateStringArgument(iniarg))) return FALSE;
-
- if ((g = getgrnam(iniarg)))
- gid = g->gr_gid;
- else
- success = !GetNumericId(&gid, iniarg);
- break;
- }
-
- case INI_PARAM_UID:
- {
- struct passwd *p;
- IniFileErrorMessage = "Invalid user id or name";
- if (!(uname = allocateStringArgument(iniarg))) return FALSE;
-
- if ((p = getpwnam(iniarg)))
- uid = p->pw_uid;
- else
- success = !GetNumericId(&uid, iniarg);
- break;
- }
-
-# endif // !defined(NO_USER_SWITCH) && !defined(_WIN32)
-
-# ifndef NO_RANDOM_EPID
-
- case INI_PARAM_LCID:
- success = getIniFileArgumentInt(&result, iniarg, 0, 32767);
- if (success) Lcid = (uint16_t)result;
- break;
-
- case INI_PARAM_RANDOMIZATION_LEVEL:
- success = getIniFileArgumentInt(&result, iniarg, 0, 2);
- if (success) RandomizationLevel = (int_fast8_t)result;
- break;
-
-# endif // NO_RANDOM_EPID
-
-# ifdef USE_MSRPC
-
- case INI_PARAM_PORT:
- defaultport = allocateStringArgument(iniarg);
- break;
-
-# endif // USE_MSRPC
-
-# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
- case INI_PARAM_LISTEN:
- maxsockets++;
- return TRUE;
-
-# if !defined(NO_LIMIT) && !__minix__
-
- case INI_PARAM_MAX_WORKERS:
-# ifdef USE_MSRPC
- success = getIniFileArgumentInt(&MaxTasks, iniarg, 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT);
-# else // !USE_MSRPC
- success = getIniFileArgumentInt(&MaxTasks, iniarg, 1, SEM_VALUE_MAX);
-# endif // !USE_MSRPC
- break;
-
-# endif // !defined(NO_LIMIT) && !__minix__
-# endif // NO_SOCKETS
-
-# ifndef NO_PID_FILE
-
- case INI_PARAM_PID_FILE:
- fn_pid = allocateStringArgument(iniarg);
- break;
-
-# endif // NO_PID_FILE
-
-# ifndef NO_LOG
-
- case INI_PARAM_LOG_FILE:
- fn_log = allocateStringArgument(iniarg);
- break;
-
-# ifndef NO_VERBOSE_LOG
- case INI_PARAM_LOG_VERBOSE:
- success = getIniFileArgumentBool(&logverbose, iniarg);
- break;
-
-# endif // NO_VERBOSE_LOG
-# endif // NO_LOG
-
-# ifndef NO_CUSTOM_INTERVALS
-
- case INI_PARAM_ACTIVATION_INTERVAL:
- success = getTimeSpanFromIniFile(&VLActivationInterval, iniarg);
- break;
-
- case INI_PARAM_RENEWAL_INTERVAL:
- success = getTimeSpanFromIniFile(&VLRenewalInterval, iniarg);
- break;
-
-# endif // NO_CUSTOM_INTERVALS
-
-# ifndef USE_MSRPC
-
-# if !defined(NO_TIMEOUT) && !__minix__
-
- case INI_PARAM_CONNECTION_TIMEOUT:
- success = getIniFileArgumentInt(&result, iniarg, 1, 600);
- if (success) ServerTimeout = (DWORD)result;
- break;
-
-# endif // !defined(NO_TIMEOUT) && !__minix__
-
- case INI_PARAM_DISCONNECT_IMMEDIATELY:
- success = getIniFileArgumentBool(&DisconnectImmediately, iniarg);
- break;
-
- case INI_PARAM_RPC_NDR64:
- success = getIniFileArgumentBool(&UseRpcNDR64, iniarg);
- break;
-
- case INI_PARAM_RPC_BTFN:
- success = getIniFileArgumentBool(&UseRpcBTFN, iniarg);
- break;
-
-# endif // USE_MSRPC
-
- default:
- return FALSE;
- }
-
- return success;
-}
-
-
-static __pure int isControlCharOrSlash(const char c)
-{
- if ((unsigned char)c < '!') return !0;
- if (c == '/') return !0;
- return 0;
-}
-
-
-static void iniFileLineNextWord(const char **s)
-{
- while ( **s && isspace((int)**s) ) (*s)++;
-}
-
-
-static BOOL setHwIdFromIniFileLine(const char **s, const ProdListIndex_t index)
-{
- iniFileLineNextWord(s);
-
- if (**s == '/')
- {
- if (KmsResponseParameters[index].HwId) return TRUE;
-
- BYTE* HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6 *)0)->HwId));
- hex2bin(HwId, *s + 1, sizeof(((RESPONSE_V6 *)0)->HwId));
- KmsResponseParameters[index].HwId = HwId;
- }
-
- return TRUE;
-}
-
-
-static BOOL checkGuidInIniFileLine(const char **s, ProdListIndex_t *const index)
-{
- GUID AppGuid;
-
- if (!string2Uuid(*s, &AppGuid)) return FALSE;
-
- (*s) += GUID_STRING_LENGTH;
- getProductNameHE(&AppGuid, AppList, index);
-
- if (*index > getAppListSize() - 2)
- {
- IniFileErrorMessage = "Unknown App Guid.";
- return FALSE;
- }
-
- iniFileLineNextWord(s);
- if ( *(*s)++ != '=' ) return FALSE;
-
- return TRUE;
-}
-
-
-static BOOL setEpidFromIniFileLine(const char **s, const ProdListIndex_t index)
-{
- iniFileLineNextWord(s);
- const char *savedPosition = *s;
- uint_fast16_t i;
-
- for (i = 0; !isControlCharOrSlash(**s); i++)
- {
- if (utf8_to_ucs2_char((const unsigned char*)*s, (const unsigned char**)s) == (WCHAR)~0)
- {
- return FALSE;
- }
- }
-
- if (i < 1 || i >= PID_BUFFER_SIZE) return FALSE;
- if (KmsResponseParameters[index].Epid) return TRUE;
-
- size_t size = *s - savedPosition + 1;
-
- char* epidbuffer = (char*)vlmcsd_malloc(size);
- memcpy(epidbuffer, savedPosition, size - 1);
- epidbuffer[size - 1] = 0;
-
- KmsResponseParameters[index].Epid = epidbuffer;
-
- #ifndef NO_LOG
- KmsResponseParameters[index].EpidSource = fn_ini;
- #endif //NO_LOG
-
- return TRUE;
-}
-
-
-static BOOL getIniFileArgument(const char **s)
-{
- while (!isspace((int)**s) && **s != '=' && **s) (*s)++;
- iniFileLineNextWord(s);
-
- if (*((*s)++) != '=')
- {
- IniFileErrorMessage = "'=' required after keyword.";
- return FALSE;
- }
-
- iniFileLineNextWord(s);
-
- if (!**s)
- {
- IniFileErrorMessage = "missing argument after '='.";
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-static BOOL handleIniFileParameter(const char *s)
-{
- uint_fast8_t i;
-
- for (i = 0; i < _countof(IniFileParameterList); i++)
- {
- if (strncasecmp(IniFileParameterList[i].Name, s, strlen(IniFileParameterList[i].Name))) continue;
- if (!IniFileParameterList[i].Id) return TRUE;
-
- if (!getIniFileArgument(&s)) return FALSE;
-
- return setIniFileParameter(IniFileParameterList[i].Id, s);
- }
-
- IniFileErrorMessage = "Unknown keyword.";
- return FALSE;
-}
-
-
-#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-static BOOL setupListeningSocketsFromIniFile(const char *s)
-{
- if (!maxsockets) return TRUE;
- if (strncasecmp("Listen", s, 6)) return TRUE;
- if (!getIniFileArgument(&s)) return TRUE;
-
- snprintf(IniFileErrorBuffer, INIFILE_ERROR_BUFFERSIZE, "Cannot listen on %s.", s);
- IniFileErrorMessage = IniFileErrorBuffer;
- return addListeningSocket(s);
-}
-#endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
-
-static BOOL readIniFile(const uint_fast8_t pass)
-{
- char line[256];
- const char *s;
- ProdListIndex_t appIndex;
- unsigned int lineNumber;
- uint_fast8_t lineParseError;
-
- FILE *restrict f;
- BOOL result = TRUE;
-
- IniFileErrorBuffer = (char*)vlmcsd_malloc(INIFILE_ERROR_BUFFERSIZE);
-
- if ( !(f = fopen(fn_ini, "r") )) return FALSE;
-
- for (lineNumber = 1; (s = fgets(line, sizeof(line), f)); lineNumber++)
- {
- line[strlen(line) - 1] = 0;
-
- iniFileLineNextWord(&s);
- if (*s == ';' || *s == '#' || !*s) continue;
-
-# ifndef NO_SOCKETS
- if (pass == INI_FILE_PASS_1)
-# endif // NO_SOCKETS
- {
- if (handleIniFileParameter(s)) continue;
-
- lineParseError = !checkGuidInIniFileLine(&s, &appIndex) ||
- !setEpidFromIniFileLine(&s, appIndex) ||
- !setHwIdFromIniFileLine(&s, appIndex);
- }
-# if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- else if (pass == INI_FILE_PASS_2)
- {
- lineParseError = !setupListeningSocketsFromIniFile(s);
- }
- else
- {
- return FALSE;
- }
-# endif // NO_SOCKETS
-
- if (lineParseError)
- {
- printerrorf("Warning: %s line %u: \"%s\". %s\n", fn_ini, lineNumber, line, IniFileErrorMessage);
- continue;
- }
- }
-
- if (ferror(f)) result = FALSE;
-
- free(IniFileErrorBuffer);
- fclose(f);
-
-# if !defined(NO_SOCKETS) && !defined(NO_LOG)
-
- if (pass == INI_FILE_PASS_1 && !InetdMode && result)
- {
-# ifdef _NTSERVICE
- if (!installService)
-# endif // _NTSERVICE
- logger("Read ini file %s\n", fn_ini);
- }
-
-# endif // !defined(NO_SOCKETS) && !defined(NO_LOG)
-
- return result;
-}
-#endif // NO_INI_FILE
-
-
-#if !defined(NO_SOCKETS)
-#if !defined(_WIN32)
-#if !defined(NO_SIGHUP)
-static void exec_self(char** argv)
-{
-# if __linux__ && defined(USE_AUXV)
-
- char *execname_ptr = (char*)getauxval(AT_EXECFN);
- if (execname_ptr) execv(execname_ptr, argv);
-
-# elif (__linux__ || __CYGWIN__) && !defined(NO_PROCFS)
-
- execv(realpath("/proc/self/exe", NULL), argv);
-
-# elif (__FreeBSD__) && !defined(NO_PROCFS)
-
- int mib[4];
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_PATHNAME;
- mib[3] = -1;
- char path[PATH_MAX + 1];
- size_t cb = sizeof(path);
- if (!sysctl(mib, 4, path, &cb, NULL, 0)) execv(path, argv);
-
-# elif (__DragonFly__) && !defined(NO_PROCFS)
-
- execv(realpath("/proc/curproc/file", NULL), argv);
-
-# elif __NetBSD__ && !defined(NO_PROCFS)
-
- execv(realpath("/proc/curproc/exe", NULL), argv);
-
-# elif __sun__
-
- const char* exename = getexecname();
- if (exename) execv(exename, argv);
-
-# elif __APPLE__
-
- char path[PATH_MAX + 1];
- uint32_t size = sizeof(path);
- if (_NSGetExecutablePath(path, &size) == 0) execv(path, argv);
-
-# else
-
- execvp(argv[0], argv);
-
-# endif
-}
-
-
-static void HangupHandler(const int signal_unused)
-{
- int i;
- int_fast8_t daemonize_protection = TRUE;
- CARGV argv_in = multi_argv == NULL ? global_argv : multi_argv;
- int argc_in = multi_argc == 0 ? global_argc : multi_argc;
- const char** argv_out = (const char**)vlmcsd_malloc((argc_in + 2) * sizeof(char**));
-
- for (i = 0; i < argc_in; i++)
- {
- if (!strcmp(argv_in[i], "-Z")) daemonize_protection = FALSE;
- argv_out[i] = argv_in[i];
- }
-
- argv_out[argc_in] = argv_out[argc_in + 1] = NULL;
- if (daemonize_protection) argv_out[argc_in] = (char*) "-Z";
-
- exec_self((char**)argv_out);
-
-# ifndef NO_LOG
- logger("Fatal: Unable to restart on SIGHUP: %s\n", strerror(errno));
-# endif
-
-# ifndef NO_PID_FILE
- if (fn_pid) unlink(fn_pid);
-# endif // NO_PID_FILE
- exit(errno);
-}
-#endif // NO_SIGHUP
-
-
-static void terminationHandler(const int signal_unused)
-{
- cleanup();
- exit(0);
-}
-
-
-#if defined(CHILD_HANDLER) || __minix__
-static void childHandler(const int signal)
-{
- waitpid(-1, NULL, WNOHANG);
-}
-#endif // defined(CHILD_HANDLER) || __minix__
-
-
-static int daemonizeAndSetSignalAction()
-{
- struct sigaction sa;
- sigemptyset(&sa.sa_mask);
-
-# ifndef NO_LOG
- if ( !nodaemon) if (daemon(!0, logstdout))
-# else // NO_LOG
- if ( !nodaemon) if (daemon(!0, 0))
-# endif // NO_LOG
- {
- printerrorf("Fatal: Could not daemonize to background.\n");
- return(errno);
- }
-
- if (!InetdMode)
- {
-# ifndef USE_THREADS
-
-# if defined(CHILD_HANDLER) || __minix__
- sa.sa_handler = childHandler;
-# else // !(defined(CHILD_HANDLER) || __minix__)
- sa.sa_handler = SIG_IGN;
-# endif // !(defined(CHILD_HANDLER) || __minix__)
- sa.sa_flags = SA_NOCLDWAIT;
-
- if (sigaction(SIGCHLD, &sa, NULL))
- return(errno);
-
-# endif // !USE_THREADS
-
- sa.sa_handler = terminationHandler;
- sa.sa_flags = 0;
-
- sigaction(SIGINT, &sa, NULL);
- sigaction(SIGTERM, &sa, NULL);
-
-# ifndef NO_SIGHUP
- sa.sa_handler = HangupHandler;
- sa.sa_flags = SA_NODEFER;
- sigaction(SIGHUP, &sa, NULL);
-# endif // NO_SIGHUP
- }
-
- return 0;
-}
-
-
-#else // _WIN32
-
-static BOOL terminationHandler(const DWORD fdwCtrlType)
-{
- // What a lame substitute for Unix signal handling
- switch(fdwCtrlType)
- {
- case CTRL_C_EVENT:
- case CTRL_CLOSE_EVENT:
- case CTRL_BREAK_EVENT:
- case CTRL_LOGOFF_EVENT:
- case CTRL_SHUTDOWN_EVENT:
- cleanup();
- exit(0);
- default:
- return FALSE;
- }
-}
-
-
-static DWORD daemonizeAndSetSignalAction()
-{
- if(!SetConsoleCtrlHandler( (PHANDLER_ROUTINE) terminationHandler, TRUE ))
- {
- #ifndef NO_LOG
- DWORD rc = GetLastError();
- logger("Warning: Could not register Windows signal handler: Error %u\n", rc);
- #endif // NO_LOG
- }
-
- return ERROR_SUCCESS;
-}
-#endif // _WIN32
-#endif // !defined(NO_SOCKETS)
-
-
-// Workaround for Cygwin fork bug (only affects cygwin processes that are Windows services)
-// Best is to compile for Cygwin with threads. fork() is slow and unreliable on Cygwin
-#if !defined(NO_INI_FILE) || !defined(NO_LOG) || !defined(NO_CL_PIDS)
-__pure static char* getCommandLineArg(char *const restrict optarg)
-{
- #if !defined (__CYGWIN__) || defined(USE_THREADS) || defined(NO_SOCKETS)
- return optarg;
- #else
- if (!IsNTService) return optarg;
-
- return allocateStringArgument(optarg);
- #endif
-}
-#endif // !defined(NO_INI_FILE) || !defined(NO_LOG) || !defined(NO_CL_PIDS)
-
-
-static void parseGeneralArguments() {
- int o;
-
- #ifndef NO_CL_PIDS
- BYTE* HwId;
- #endif // NO_CL_PIDS
-
- for (opterr = 0; ( o = getopt(global_argc, (char* const*)global_argv, optstring) ) > 0; ) switch (o)
- {
- #if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
- case 'Z':
- IsRestarted = TRUE;
- nodaemon = TRUE;
- break;
- #endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
-
- #ifndef NO_CL_PIDS
- case 'w':
- KmsResponseParameters[APP_ID_WINDOWS].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[APP_ID_WINDOWS].EpidSource = "command line";
- #endif // NO_LOG
- break;
-
- case '0':
- KmsResponseParameters[APP_ID_OFFICE2010].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[APP_ID_OFFICE2010].EpidSource = "command line";
- #endif // NO_LOG
- break;
-
- case '3':
- KmsResponseParameters[APP_ID_OFFICE2013].Epid = getCommandLineArg(optarg);
- #ifndef NO_LOG
- KmsResponseParameters[APP_ID_OFFICE2013].EpidSource = "command line";
- #endif // NO_LOG
- break;
-
- case 'H':
- HwId = (BYTE*)vlmcsd_malloc(sizeof(((RESPONSE_V6 *)0)->HwId));
-
- hex2bin(HwId, optarg, sizeof(((RESPONSE_V6 *)0)->HwId));
-
- KmsResponseParameters[APP_ID_WINDOWS].HwId = HwId;
- KmsResponseParameters[APP_ID_OFFICE2010].HwId = HwId;
- KmsResponseParameters[APP_ID_OFFICE2013].HwId = HwId;
- break;
- #endif // NO_CL_PIDS
-
- #ifndef NO_SOCKETS
-
- #ifndef USE_MSRPC
- case '4':
- case '6':
- case 'P':
- ignoreIniFileParameter(INI_PARAM_LISTEN);
- break;
- #else // USE_MSRPC
- case 'P':
- defaultport = optarg;
- ignoreIniFileParameter(INI_PARAM_PORT);
- break;
- #endif // USE_MSRPC
-
- #if !defined(NO_LIMIT) && !__minix__
-
- case 'm':
- #ifdef USE_MSRPC
- MaxTasks = getOptionArgumentInt(o, 1, RPC_C_LISTEN_MAX_CALLS_DEFAULT);
- #else // !USE_MSRPC
- MaxTasks = getOptionArgumentInt(o, 1, SEM_VALUE_MAX);
- #endif // !USE_MSRPC
- ignoreIniFileParameter(INI_PARAM_MAX_WORKERS);
- break;
-
- #endif // !defined(NO_LIMIT) && !__minix__
- #endif // NO_SOCKETS
-
- #if !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC)
- case 't':
- ServerTimeout = getOptionArgumentInt(o, 1, 600);
- ignoreIniFileParameter(INI_PARAM_CONNECTION_TIMEOUT);
- break;
- #endif // !defined(NO_TIMEOUT) && !__minix__ && !defined(USE_MSRPC)
-
- #ifndef NO_PID_FILE
- case 'p':
- fn_pid = getCommandLineArg(optarg);
- ignoreIniFileParameter(INI_PARAM_PID_FILE);
- break;
- #endif
-
- #ifndef NO_INI_FILE
- case 'i':
- fn_ini = getCommandLineArg(optarg);
- if (!strcmp(fn_ini, "-")) fn_ini = NULL;
- break;
- #endif
-
- #ifndef NO_LOG
- case 'l':
- fn_log = getCommandLineArg(optarg);
- ignoreIniFileParameter(INI_PARAM_LOG_FILE);
- break;
-
- #ifndef NO_VERBOSE_LOG
- case 'v':
- case 'q':
- logverbose = o == 'v';
- ignoreIniFileParameter(INI_PARAM_LOG_VERBOSE);
- break;
-
- #endif // NO_VERBOSE_LOG
- #endif // NO_LOG
-
- #ifndef NO_SOCKETS
- #ifndef USE_MSRPC
- case 'L':
- maxsockets++;
- ignoreIniFileParameter(INI_PARAM_LISTEN);
- break;
- #endif // USE_MSRPC
-
- case 'f':
- nodaemon = 1;
- #ifndef NO_LOG
- logstdout = 1;
- #endif
- break;
-
- #ifdef _NTSERVICE
- case 'U':
- ServiceUser = optarg;
- break;
-
- case 'W':
- ServicePassword = optarg;
- break;
-
- case 's':
- #ifndef USE_MSRPC
- if (InetdMode) usage();
- #endif // USE_MSRPC
- if (!IsNTService) installService = 1; // Install
- break;
-
- case 'S':
- if (!IsNTService) installService = 2; // Remove
- break;
- #endif // _NTSERVICE
-
- case 'D':
- nodaemon = 1;
- break;
-
- #ifndef NO_LOG
- case 'e':
- logstdout = 1;
- break;
- #endif // NO_LOG
- #endif // NO_SOCKETS
-
- #ifndef _WIN32
- case 'I': // Backward compatibility with svn681 and earlier
- break;
- #endif // _WIN32
-
- #ifndef NO_RANDOM_EPID
- case 'r':
- RandomizationLevel = (int_fast8_t)getOptionArgumentInt(o, 0, 2);
- ignoreIniFileParameter(INI_PARAM_RANDOMIZATION_LEVEL);
- break;
-
- case 'C':
- Lcid = (uint16_t)getOptionArgumentInt(o, 0, 32767);
-
- ignoreIniFileParameter(INI_PARAM_LCID);
-
- #ifdef _PEDANTIC
- if (!IsValidLcid(Lcid))
- {
- printerrorf("Warning: %s is not a valid LCID.\n", optarg);
- }
- #endif // _PEDANTIC
-
- break;
- #endif // NO_RANDOM_PID
-
- #if !defined(NO_USER_SWITCH) && !defined(_WIN32)
- case 'g':
- gname = optarg;
- ignoreIniFileParameter(INI_PARAM_GID);
- #ifndef NO_SIGHUP
- if (!IsRestarted)
- #endif // NO_SIGHUP
- if (GetGid())
- {
- printerrorf("Fatal: setgid for %s failed.\n", optarg);
- exit(!0);
- }
- break;
-
- case 'u':
- uname = optarg;
- ignoreIniFileParameter(INI_PARAM_UID);
- #ifndef NO_SIGHUP
- if (!IsRestarted)
- #endif // NO_SIGHUP
- if (GetUid())
- {
- printerrorf("Fatal: setuid for %s failed.\n", optarg);
- exit(!0);
- }
- break;
- #endif // NO_USER_SWITCH && !_WIN32
-
- #ifndef NO_CUSTOM_INTERVALS
- case 'R':
- VLRenewalInterval = getTimeSpanFromCommandLine(optarg, o);
- ignoreIniFileParameter(INI_PARAM_RENEWAL_INTERVAL);
- break;
-
- case 'A':
- VLActivationInterval = getTimeSpanFromCommandLine(optarg, o);
- ignoreIniFileParameter(INI_PARAM_ACTIVATION_INTERVAL);
- break;
- #endif
-
- #ifndef USE_MSRPC
- case 'd':
- case 'k':
- DisconnectImmediately = o == 'd';
- ignoreIniFileParameter(INI_PARAM_DISCONNECT_IMMEDIATELY);
- break;
-
- case 'N':
- if (!getArgumentBool(&UseRpcNDR64, optarg)) usage();
- ignoreIniFileParameter(INI_PARAM_RPC_NDR64);
- break;
-
- case 'B':
- if (!getArgumentBool(&UseRpcBTFN, optarg)) usage();
- ignoreIniFileParameter(INI_PARAM_RPC_BTFN);
- break;
- #endif // !USE_MSRPC
-
- case 'V':
- #ifdef _NTSERVICE
- if (IsNTService) break;
- #endif
- printf("vlmcsd %s\n", Version);
- exit(0);
-
- default:
- usage();
- }
-
- // Do not allow non-option arguments
- if (optind != global_argc)
- usage();
-
- #ifdef _NTSERVICE
- // -U and -W must be used with -s
- if ((ServiceUser || *ServicePassword) && installService != 1) usage();
- #endif // _NTSERVICE
-}
-
-
-#ifndef NO_PID_FILE
-static void writePidFile()
-{
-# ifndef NO_SIGHUP
- if (IsRestarted) return;
-# endif // NO_SIGHUP
-
- if (fn_pid && !InetdMode)
- {
- FILE *_f = fopen(fn_pid, "w");
-
- if ( _f )
- {
- fprintf(_f, "%u", (uint32_t)getpid());
- fclose(_f);
- }
-
- #ifndef NO_LOG
- else
- {
- logger("Warning: Cannot write pid file '%s'. %s.\n", fn_pid, strerror(errno));
- }
- #endif // NO_LOG
- }
-}
-#else
-#define writePidFile(x)
-#endif // NO_PID_FILE
-
-#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
-void cleanup()
-{
-
- if (!InetdMode)
- {
- #ifndef NO_PID_FILE
- if (fn_pid) unlink(fn_pid);
- #endif // NO_PID_FILE
- closeAllListeningSockets();
-
- #if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !defined(_WIN32) && !__minix__
- sem_unlink("/vlmcsd");
- #if !defined(USE_THREADS) && !defined(CYGWIN)
- if (shmid >= 0)
- {
- if (Semaphore != (sem_t*)-1) shmdt(Semaphore);
- shmctl(shmid, IPC_RMID, NULL);
- }
- #endif // !defined(USE_THREADS) && !defined(CYGWIN)
- #endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !defined(_WIN32) && !__minix__
-
- #ifndef NO_LOG
- logger("vlmcsd %s was shutdown\n", Version);
- #endif // NO_LOG
- }
-
-}
-
-#elif defined(USE_MSRPC)
-
-void cleanup()
-{
-# ifndef NO_PID_FILE
- if (fn_pid) unlink(fn_pid);
-# endif // NO_PID_FILE
-
-# ifndef NO_LOG
- logger("vlmcsd %s was shutdown\n", Version);
-# endif // NO_LOG
-}
-
-#else // Neither Sockets nor RPC
-
-__pure void cleanup() {}
-
-#endif // Neither Sockets nor RPC
-
-
-#if !defined(USE_MSRPC) && !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
-// Get a semaphore for limiting the maximum concurrent tasks
-static void allocateSemaphore(void)
-{
- #ifdef USE_THREADS
- #define sharemode 0
- #else
- #define sharemode 1
- #endif
-
- #ifndef _WIN32
- sem_unlink("/vlmcsd");
- #endif
-
- if(MaxTasks < SEM_VALUE_MAX && !InetdMode)
- {
- #ifndef _WIN32
-
- #if !defined(USE_THREADS) && !defined(CYGWIN)
-
- if ((Semaphore = sem_open("/vlmcsd", O_CREAT /*| O_EXCL*/, 0700, MaxTasks)) == SEM_FAILED) // fails on many systems
- {
- // We didn't get a named Semaphore (/dev/shm on Linux) so let's try our own shared page
-
- if (
- ( shmid = shmget(IPC_PRIVATE, sizeof(sem_t), IPC_CREAT | 0600) ) < 0 ||
- ( Semaphore = (sem_t*)shmat(shmid, NULL, 0) ) == (sem_t*)-1 ||
- sem_init(Semaphore, 1, MaxTasks) < 0
- )
- {
- int errno_save = errno;
- if (Semaphore != (sem_t*)-1) shmdt(Semaphore);
- if (shmid >= 0) shmctl(shmid, IPC_RMID, NULL);
- printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno_save));
- MaxTasks = SEM_VALUE_MAX;
- }
- }
-
- #else // THREADS or CYGWIN
-
- Semaphore = (sem_t*)vlmcsd_malloc(sizeof(sem_t));
-
- if (sem_init(Semaphore, sharemode, MaxTasks) < 0) // sem_init is not implemented on Darwin (returns ENOSYS)
- {
- free(Semaphore);
-
- if ((Semaphore = sem_open("/vlmcsd", O_CREAT /*| O_EXCL*/, 0700, MaxTasks)) == SEM_FAILED)
- {
- printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(errno));
- MaxTasks = SEM_VALUE_MAX;
- }
- }
-
- #endif // THREADS or CYGWIN
-
- #else // _WIN32
-
- if (!(Semaphore = CreateSemaphoreA(NULL, MaxTasks, MaxTasks, NULL)))
- {
- printerrorf("Warning: Could not create semaphore: %s\n", vlmcsd_strerror(GetLastError()));
- MaxTasks = SEM_VALUE_MAX;
- }
-
- #endif // _WIN32
- }
-}
-#endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__
-
-
-#if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-int setupListeningSockets()
-{
- int o;
- uint_fast8_t allocsockets = maxsockets ? maxsockets : 2;
-
- SocketList = (SOCKET*)vlmcsd_malloc((size_t)allocsockets * sizeof(SOCKET));
-
- haveIPv4Stack = checkProtocolStack(AF_INET);
- haveIPv6Stack = checkProtocolStack(AF_INET6);
-
- // Reset getopt since we've alread used it
- optReset();
-
- for (opterr = 0; ( o = getopt(global_argc, (char* const*)global_argv, optstring) ) > 0; ) switch (o)
- {
- case '4':
-
- if (!haveIPv4Stack)
- {
- printerrorf("Fatal: Your system does not support %s.\n", cIPv4);
- return !0;
- }
- v4required = 1;
- break;
-
- case '6':
-
- if (!haveIPv6Stack)
- {
- printerrorf("Fatal: Your system does not support %s.\n", cIPv6);
- return !0;
- }
- v6required = 1;
- break;
-
- case 'L':
-
- addListeningSocket(optarg);
- break;
-
- case 'P':
-
- defaultport = optarg;
- break;
-
- default:
-
- break;
- }
-
-
-# ifndef NO_INI_FILE
- if (maxsockets && !numsockets)
- {
- if (fn_ini && !readIniFile(INI_FILE_PASS_2))
- {
- #ifdef INI_FILE
- if (strcmp(fn_ini, INI_FILE))
- #endif // INI_FILE
- printerrorf("Warning: Can't read %s: %s\n", fn_ini, strerror(errno));
- }
- }
-# endif
-
- // if -L hasn't been specified on the command line, use default sockets (all IP addresses)
- // maxsocket results from first pass parsing the arguments
- if (!maxsockets)
- {
- if (haveIPv6Stack && (v6required || !v4required)) addListeningSocket("::");
- if (haveIPv4Stack && (v4required || !v6required)) addListeningSocket("0.0.0.0");
- }
-
- if (!numsockets)
- {
- printerrorf("Fatal: Could not listen on any socket.\n");
- return(!0);
- }
-
- return 0;
-}
-#endif // !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
-
-int server_main(int argc, CARGV argv)
-{
- #if !defined(_NTSERVICE) && !defined(NO_SOCKETS)
- int error;
- #endif // !defined(_NTSERVICE) && !defined(NO_SOCKETS)
-
- // Initialize ePID / HwId parameters
- memset(KmsResponseParameters, 0, sizeof(KmsResponseParameters));
-
- global_argc = argc;
- global_argv = argv;
-
- #ifdef _NTSERVICE // #endif is in newmain()
- DWORD lasterror = ERROR_SUCCESS;
-
- if (!StartServiceCtrlDispatcher(NTServiceDispatchTable) && (lasterror = GetLastError()) == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
- {
- IsNTService = FALSE;
- return newmain();
- }
-
- return lasterror;
-}
-
-
-int newmain()
-{
- int error;
-
- // Initialize thread synchronization objects for Windows and Cygwin
- #ifdef USE_THREADS
-
- #ifndef NO_LOG
- // Initialize the Critical Section for proper logging
- InitializeCriticalSection(&logmutex);
- #endif // NO_LOG
-
- #endif // USE_THREADS
-
- #ifdef _WIN32
-
- #ifndef USE_MSRPC
- // Windows Sockets must be initialized
- WSADATA wsadata;
-
- if ((error = WSAStartup(0x0202, &wsadata)))
- {
- printerrorf("Fatal: Could not initialize Windows sockets (Error: %d).\n", error);
- return error;
- }
- #endif // USE_MSRPC
-
- // Windows can never daemonize
- nodaemon = 1;
-
- #else // __CYGWIN__
-
- // Do not daemonize if we are a Windows service
- if (IsNTService) nodaemon = 1;
-
- #endif // _WIN32 / __CYGWIN__
- #endif // _NTSERVICE ( #ifdef is main(int argc, CARGV argv) )
-
- parseGeneralArguments(); // Does not return if an error occurs
-
- #if !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- struct stat statbuf;
- fstat(STDIN_FILENO, &statbuf);
- if (S_ISSOCK(statbuf.st_mode))
- {
- InetdMode = 1;
- nodaemon = 1;
- maxsockets = 0;
- #ifndef NO_LOG
- logstdout = 0;
- #endif // NO_LOG
- }
- #endif // !defined(_WIN32) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
- #ifndef NO_INI_FILE
- if (fn_ini && !readIniFile(INI_FILE_PASS_1))
- {
- #ifdef INI_FILE
- if (strcmp(fn_ini, INI_FILE))
- #endif // INI_FILE
- printerrorf("Warning: Can't read %s: %s\n", fn_ini, strerror(errno));
- }
- #endif // NO_INI_FILE
-
- #if !defined(NO_LIMIT) && !defined(NO_SOCKETS) && !__minix__ && !defined(USE_MSRPC)
- allocateSemaphore();
- #endif // !defined(NO_LIMIT) && !defined(NO_SOCKETS) && __minix__
-
- #ifdef _NTSERVICE
- if (installService)
- return NtServiceInstallation(installService, ServiceUser, ServicePassword);
- #endif // _NTSERVICE
-
- #if !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- if (!InetdMode)
- {
- if ((error = setupListeningSockets())) return error;
- }
- #endif // NO_SOCKETS
-
- // After sockets have been set up, we may switch to a lower privileged user
- #if !defined(_WIN32) && !defined(NO_USER_SWITCH)
-
- #ifndef NO_SIGHUP
- if (!IsRestarted)
- {
- #endif // NO_SIGHUP
- if (gid != INVALID_GID && setgid(gid))
- {
- printerrorf("Fatal: setgid for %s failed.\n", gname);
- return !0;
- }
-
- if (uid != INVALID_UID && setuid(uid))
- {
- printerrorf("Fatal: setuid for %s failed.\n", uname);
- return !0;
- }
- #ifndef NO_SIGHUP
- }
- #endif // NO_SIGHUP
-
- #endif // !defined(_WIN32) && !defined(NO_USER_SWITCH)
-
- randomNumberInit();
-
- // Randomization Level 1 means generate ePIDs at startup and use them during
- // the lifetime of the process. So we generate them now
- #ifndef NO_RANDOM_EPID
- if (RandomizationLevel == 1) randomPidInit();
- #endif
-
- #if !defined(NO_SOCKETS)
- #ifdef _WIN32
- if (!IsNTService)
- #endif // _WIN32
- if ((error = daemonizeAndSetSignalAction())) return error;
- #endif // !defined(NO_SOCKETS)
-
- writePidFile();
-
- #if !defined(NO_LOG) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
- if (!InetdMode)
- logger("vlmcsd %s started successfully\n", Version);
- #endif // !defined(NO_LOG) && !defined(NO_SOCKETS) && !defined(USE_MSRPC)
-
- #if defined(_NTSERVICE) && !defined(USE_MSRPC)
- if (IsNTService) ReportServiceStatus(SERVICE_RUNNING, NO_ERROR, 200);
- #endif // defined(_NTSERVICE) && !defined(USE_MSRPC)
-
- int rc;
- rc = runServer();
-
- // Clean up things and exit
- #ifdef _NTSERVICE
- if (!ServiceShutdown)
- #endif
- cleanup();
- #ifdef _NTSERVICE
- else
- ReportServiceStatus(SERVICE_STOPPED, NO_ERROR, 0);
- #endif
-
- return rc;
-}
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include "vlmcs.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#ifndef _WIN32
-#include
-#include
-#else // _WIN32
-#endif // _WIN32
-#include "endian.h"
-#include "shared_globals.h"
-#include "output.h"
-#ifndef USE_MSRPC
-#include "network.h"
-#include "rpc.h"
-#else // USE_MSRPC
-#include "msrpc-client.h"
-#endif // USE_MSRPC
-#include "kms.h"
-#include "helpers.h"
-#include "dns_srv.h"
-
-
-#define VLMCS_OPTION_GRAB_INI 1
-#define VLMCS_OPTION_NO_GRAB_INI 2
-
-#define kmsVersionMinor 0 // Currently constant. May change in future KMS versions
-
-// Function Prototypes
-static void CreateRequestBase(REQUEST *Request);
-
-
-// KMS Parameters
-static int_fast8_t verbose = FALSE;
-static int_fast8_t VMInfo = FALSE;
-static int_fast8_t dnsnames = TRUE;
-static int FixedRequests = 0;
-static BYTE LicenseStatus = 0x02;
-static const char *CMID = NULL;
-static const char *CMID_prev = NULL;
-static const char *WorkstationName = NULL;
-static int BindingExpiration = 43200; //30 days
-static const char *RemoteAddr;
-static int_fast8_t ReconnectForEachRequest = FALSE;
-static int AddressFamily = AF_UNSPEC;
-static int_fast8_t incompatibleOptions = 0;
-static const char* fn_ini_client = NULL;
-
-#ifndef NO_DNS
-static int_fast8_t NoSrvRecordPriority = FALSE;
-#endif // NO_DNS
-
-
-// Structure for handling "License Packs" (e.g. Office2013v5 or WindowsVista)
-typedef struct
-{
- const char *names; //This is a list of strings. Terminate with additional Zero!!!
- int N_Policy;
- int kmsVersionMajor;
- const GUID *AppID;
- GUID ActID;
- GUID KMSID;
-} LicensePack;
-
-
-typedef char iniFileEpidLines[3][256];
-
-// Well known "license packs"
-static const LicensePack LicensePackList[] =
-{
- // List of names min lics version appID skuId KMSCountedID
- /* 000 */ { "Vista\000W6\000"
- "WindowsVista\000"
- "Windows\000", 25, 4, PWINGUID, { 0x4f3d1606, 0x3fea, 0x4c01, { 0xbe, 0x3c, 0x8d, 0x67, 0x1c, 0x40, 0x1e, 0x3b, } }, { 0x212a64dc, 0x43b1, 0x4d3d, { 0xa3, 0x0c, 0x2f, 0xc6, 0x9d, 0x20, 0x95, 0xc6 } } },
- /* 001 */ { "W7\000Windows7\000", 25, 4, PWINGUID, { 0xb92e9980, 0xb9d5, 0x4821, { 0x9c, 0x94, 0x14, 0x0f, 0x63, 0x2f, 0x63, 0x12, } }, { 0x7fde5219, 0xfbfa, 0x484a, { 0x82, 0xc9, 0x34, 0xd1, 0xad, 0x53, 0xe8, 0x56 } } },
- /* 002 */ { "W8\000Windows8\000", 25, 5, PWINGUID, { 0xa98bcd6d, 0x5343, 0x4603, { 0x8a, 0xfe, 0x59, 0x08, 0xe4, 0x61, 0x11, 0x12, } }, { 0x3c40b358, 0x5948, 0x45af, { 0x92, 0x3b, 0x53, 0xd2, 0x1f, 0xcc, 0x7e, 0x79 } } },
- /* 003 */ { "W8C\000Windows8C\000", 25, 5, PWINGUID, { 0xc04ed6bf, 0x55c8, 0x4b47, { 0x9f, 0x8e, 0x5a, 0x1f, 0x31, 0xce, 0xee, 0x60, } }, { 0xbbb97b3b, 0x8ca4, 0x4a28, { 0x97, 0x17, 0x89, 0xfa, 0xbd, 0x42, 0xc4, 0xac } } },
- /* 004 */ { "W81\000Windows81\000", 25, 6, PWINGUID, { 0xc06b6981, 0xd7fd, 0x4a35, { 0xb7, 0xb4, 0x05, 0x47, 0x42, 0xb7, 0xaf, 0x67, } }, { 0xcb8fc780, 0x2c05, 0x495a, { 0x97, 0x10, 0x85, 0xaf, 0xff, 0xc9, 0x04, 0xd7 } } },
- /* 005 */ { "W81C\000Windows81C\000", 25, 6, PWINGUID, { 0xfe1c3238, 0x432a, 0x43a1, { 0x8e, 0x25, 0x97, 0xe7, 0xd1, 0xef, 0x10, 0xf3, } }, { 0x6d646890, 0x3606, 0x461a, { 0x86, 0xab, 0x59, 0x8b, 0xb8, 0x4a, 0xce, 0x82 } } },
- /* 006 */ { "W10\000Windows10\000", 25, 6, PWINGUID, { 0x73111121, 0x5638, 0x40f6, { 0xbc, 0x11, 0xf1, 0xd7, 0xb0, 0xd6, 0x43, 0x00, } }, { 0x58e2134f, 0x8e11, 0x4d17, { 0x9c, 0xb2, 0x91, 0x06, 0x9c, 0x15, 0x11, 0x48 } } },
- /* 007 */ { "W10C\000Windows10C\000", 25, 6, PWINGUID, { 0x58e97c99, 0xf377, 0x4ef1, { 0x81, 0xd5, 0x4a, 0xd5, 0x52, 0x2b, 0x5f, 0xd8, } }, { 0xe1c51358, 0xfe3e, 0x4203, { 0xa4, 0xa2, 0x3b, 0x6b, 0x20, 0xc9, 0x73, 0x4e } } },
- /* 008 */ { "2008" "\0" "2008A\000", 5, 4, PWINGUID, { 0xddfa9f7c, 0xf09e, 0x40b9, { 0x8c, 0x1a, 0xbe, 0x87, 0x7a, 0x9a, 0x7f, 0x4b, } }, { 0x33e156e4, 0xb76f, 0x4a52, { 0x9f, 0x91, 0xf6, 0x41, 0xdd, 0x95, 0xac, 0x48 } } },
- /* 009 */ { "2008B\000", 5, 4, PWINGUID, { 0xc1af4d90, 0xd1bc, 0x44ca, { 0x85, 0xd4, 0x00, 0x3b, 0xa3, 0x3d, 0xb3, 0xb9, } }, { 0x8fe53387, 0x3087, 0x4447, { 0x89, 0x85, 0xf7, 0x51, 0x32, 0x21, 0x5a, 0xc9 } } },
- /* 010 */ { "2008C\000", 5, 4, PWINGUID, { 0x68b6e220, 0xcf09, 0x466b, { 0x92, 0xd3, 0x45, 0xcd, 0x96, 0x4b, 0x95, 0x09, } }, { 0x8a21fdf3, 0xcbc5, 0x44eb, { 0x83, 0xf3, 0xfe, 0x28, 0x4e, 0x66, 0x80, 0xa7 } } },
- /* 011 */ { "2008R2" "\0" "2008R2A\000", 5, 4, PWINGUID, { 0xa78b8bd9, 0x8017, 0x4df5, { 0xb8, 0x6a, 0x09, 0xf7, 0x56, 0xaf, 0xfa, 0x7c, } }, { 0x0fc6ccaf, 0xff0e, 0x4fae, { 0x9d, 0x08, 0x43, 0x70, 0x78, 0x5b, 0xf7, 0xed } } },
- /* 012 */ { "2008R2B\000", 5, 4, PWINGUID, { 0x620e2b3d, 0x09e7, 0x42fd, { 0x80, 0x2a, 0x17, 0xa1, 0x36, 0x52, 0xfe, 0x7a, } }, { 0xca87f5b6, 0xcd46, 0x40c0, { 0xb0, 0x6d, 0x8e, 0xcd, 0x57, 0xa4, 0x37, 0x3f } } },
- /* 013 */ { "2008R2C\000", 5, 4, PWINGUID, { 0x7482e61b, 0xc589, 0x4b7f, { 0x8e, 0xcc, 0x46, 0xd4, 0x55, 0xac, 0x3b, 0x87, } }, { 0xb2ca2689, 0xa9a8, 0x42d7, { 0x93, 0x8d, 0xcf, 0x8e, 0x9f, 0x20, 0x19, 0x58 } } },
- /* 014 */ { "2012\000", 5, 5, PWINGUID, { 0xf0f5ec41, 0x0d55, 0x4732, { 0xaf, 0x02, 0x44, 0x0a, 0x44, 0xa3, 0xcf, 0x0f, } }, { 0x8665cb71, 0x468c, 0x4aa3, { 0xa3, 0x37, 0xcb, 0x9b, 0xc9, 0xd5, 0xea, 0xac } } },
- /* 015 */ { "2012R2\000" "12R2\000", 5, 6, PWINGUID, { 0x00091344, 0x1ea4, 0x4f37, { 0xb7, 0x89, 0x01, 0x75, 0x0b, 0xa6, 0x98, 0x8c, } }, { 0x8456EFD3, 0x0C04, 0x4089, { 0x87, 0x40, 0x5b, 0x72, 0x38, 0x53, 0x5a, 0x65 } } },
- /* 016 */ { "Office2010\000O14\000", 5, 4, POFFICE2010GUID, { 0x6f327760, 0x8c5c, 0x417c, { 0x9b, 0x61, 0x83, 0x6a, 0x98, 0x28, 0x7e, 0x0c, } }, { 0xe85af946, 0x2e25, 0x47b7, { 0x83, 0xe1, 0xbe, 0xbc, 0xeb, 0xea, 0xc6, 0x11 } } },
- /* 017 */ { "Office2013\000O15\000", 5, 6, POFFICE2013GUID, { 0xb322da9c, 0xa2e2, 0x4058, { 0x9e, 0x4e, 0xf5, 0x9a, 0x69, 0x70, 0xbd, 0x69, } }, { 0xe6a6f1bf, 0x9d40, 0x40c3, { 0xaa, 0x9f, 0xc7, 0x7b, 0xa2, 0x15, 0x78, 0xc0 } } },
- /* 018 */ { "Office2013V5\000", 5, 5, POFFICE2013GUID, { 0xb322da9c, 0xa2e2, 0x4058, { 0x9e, 0x4e, 0xf5, 0x9a, 0x69, 0x70, 0xbd, 0x69, } }, { 0xe6a6f1bf, 0x9d40, 0x40c3, { 0xaa, 0x9f, 0xc7, 0x7b, 0xa2, 0x15, 0x78, 0xc0 } } },
- /* 019 */ { "Office2016\000" "O16\000", 5, 6, POFFICE2013GUID, { 0xd450596f, 0x894d, 0x49e0, { 0x96, 0x6a, 0xfd, 0x39, 0xed, 0x4c, 0x4c, 0x64, } }, { 0x85b5f61b, 0x320b, 0x4be3, { 0x81, 0x4a, 0xb7, 0x6b, 0x2b, 0xfa, 0xfc, 0x82 } } },
- /* 020 */ { NULL, 0, 0, NULL, { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } }, { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } }
-};
-
-
-typedef struct
-{
- const char* first[16];
- const char* second[16];
- const char* tld[22];
-} DnsNames;
-
-
-// Some names for the DNS name random generator
-static DnsNames ClientDnsNames =
-{
- { "www", "ftp", "kms", "hack-me", "smtp", "ns1", "mx1", "ns1", "pop3", "imap", "mail", "dns", "headquarter", "we-love", "_vlmcs._tcp", "ceo-laptop" },
- { ".microsoft", ".apple", ".amazon", ".samsung", ".adobe", ".google", ".yahoo", ".facebook", ".ubuntu", ".oracle", ".borland", ".htc", ".acer", ".windows", ".linux", ".sony" },
- { ".com", ".net", ".org", ".cn", ".co.uk", ".de", ".com.tw", ".us", ".fr", ".it", ".me", ".info", ".biz", ".co.jp", ".ua", ".at", ".es", ".pro", ".by", ".ru", ".pl", ".kr" }
-};
-
-
-// This is the one, we are actually using. We use Vista, if user selects nothing
-LicensePack ActiveLicensePack;
-
-
-// Request Count Control Variables
-static int RequestsToGo = 1;
-static BOOL firstRequestSent = FALSE;
-
-
-static void string2UuidOrExit(const char *const restrict input, GUID *const restrict guid)
-{
- if (strlen(input) != GUID_STRING_LENGTH || !string2Uuid(input, guid))
- {
- errorout("Fatal: Command line contains an invalid GUID.\n");
- exit(!0);
- }
-}
-
-
-#ifndef NO_HELP
-
-__noreturn static void clientUsage(const char* const programName)
-{
- errorout(
- "vlmcs %s \n\n"
-# ifndef NO_DNS
- "Usage: %s [options] [ [:] | . | - ] [options]\n\n"
-# else // DNS
- "Usage: %s [options] [[:]] [options]\n\n"
-# endif // DNS
-
- "Options:\n\n"
-
- " -v Be verbose\n"
- " -l \n"
- " -4 Force V4 protocol\n"
- " -5 Force V5 protocol\n"
- " -6 Force V6 protocol\n"
-# ifndef USE_MSRPC
- " -i Use IP protocol (4 or 6)\n"
-# endif // USE_MSRPC
- " -e Show some valid examples\n"
- " -x Show valid Apps\n"
- " -d no DNS names, use Netbios names (no effect if -w is used)\n\n"
-
- "Advanced options:\n\n"
-
- " -a Use custom Application GUID\n"
- " -s Use custom Activation Configuration GUID\n"
- " -k Use custom KMS GUID\n"
- " -c Use custom Client GUID. Default: Use random\n"
- " -o Use custom Prevoius Client GUID. Default: ZeroGUID\n"
- " -w Use custom workstation name. Default: Use random\n"
- " -r Fake required clients\n"
- " -n Fixed # of requests (Default: Enough to charge)\n"
- " -m Pretend to be a virtual machine\n"
- " -G Get ePID/HwId data and write to . Can't be used with -l, -4, -5, -6, -a, -s, -k, -r and -n\n"
-# ifndef USE_MSRPC
- " -T Use a new TCP connection for each request.\n"
- " -N <0|1> disable or enable NDR64. Default: 1\n"
- " -B <0|1> disable or enable RPC bind time feature negotiation. Default: 1\n"
-# endif // USE_MSRPC
- " -t Use specfic license status (0 <= T <= 6)\n"
- " -g Use a specfic binding expiration time in minutes. Default 43200\n"
-# ifndef NO_DNS
- " -P Ignore priority and weight in DNS SRV records\n"
-# endif // NO_DNS
-# ifndef USE_MSRPC
- " -p Don't use multiplexed RPC bind\n"
-# endif // USE_MSRPC
- "\n"
-
- ":\t\tTCP port name of the KMS to use. Default 1688.\n"
- ":\t\thost name of the KMS to use. Default 127.0.0.1\n"
-# ifndef NO_DNS
- ".:\tfind KMS server in via DNS\n"
-# endif // NO_DNS
- ":\t\t(Type %s -x to see a list of valid apps)\n\n",
- Version, programName, programName
- );
-
- exit(!0);
-}
-
-__pure static int getLineWidth(void)
-{
- #ifdef TERMINAL_FIXED_WIDTH // For Toolchains that to not have winsize
- return TERMINAL_FIXED_WIDTH;
- #else // Can determine width of terminal
- #ifndef _WIN32
-
- struct winsize w;
-
- if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &w))
- {
- return 80; // Return this if stdout is not a tty
- }
-
- return w.ws_col;
-
- #else // _WIN32
-
- CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
- HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
-
- if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
- {
- return 80; // Return this if stdout is not a Console
- }
-
- return csbiInfo.srWindow.Right - csbiInfo.srWindow.Left;
-
- #endif // WIN32
-
- #endif // Can determine width of terminal
-
-}
-
-__noreturn static void showProducts(PRINTFUNC p)
-{
- int cols = getLineWidth();
- int itemsPerLine;
- uint8_t i;
-
- p(
- "The following "
- #if !defined(NO_EXTENDED_PRODUCT_LIST) && !defined(NO_BASIC_PRODUCT_LIST)
- "aliases "
- #else
- "names "
- #endif
- "can be used with -l:\n\n"
- );
-
- const LicensePack* lp;
-
- itemsPerLine = cols / 20;
- if (!itemsPerLine) itemsPerLine = 1;
-
- for (i = 1, lp = LicensePackList; lp->names; lp++)
- {
- const char* name;
-
- for (name = lp->names; *name; name += strlen(name) + 1, i++)
- {
- p("%-20s", name);
-
- if (!(i % itemsPerLine)) p("\n");
- }
- }
-
- p("\n\n");
-
- #if !defined(NO_EXTENDED_PRODUCT_LIST) && !defined(NO_BASIC_PRODUCT_LIST)
-
- const KmsIdList* currentProduct;
- uint_fast8_t longestString = 0;
- uint8_t k, items = getExtendedProductListSize();
-
- p("You may also use these product names or numbers:\n\n");
-
- for (currentProduct = ExtendedProductList; currentProduct->name; currentProduct++)
- {
- uint_fast8_t len = strlen(currentProduct->name);
-
- if (len > longestString)
- longestString = len;
- }
-
- itemsPerLine = cols / (longestString + 10);
- if (!itemsPerLine) itemsPerLine = 1;
- uint8_t lines = items / itemsPerLine;
- if (items % itemsPerLine) lines++;
-
- for (i = 0; i < lines; i++)
- {
- for (k = 0; k < itemsPerLine; k++)
- {
- uint8_t j;
- uint8_t index = k * lines + i;
-
- if (index >= items) break;
-
- p("%3u = %s", index + 1, ExtendedProductList[index].name);
-
- for (j = 0; j < longestString + 4 - strlen(ExtendedProductList[index].name); j++)
- {
- p(" ");
- }
- }
-
- p("\n");
- }
-
- p("\n");
-
- #endif // !defined(NO_EXTENDED_PRODUCT_LIST) && !defined(NO_BASIC_PRODUCT_LIST)
-
- exit(0);
-}
-
-__noreturn static void examples(const char* const programName)
-{
- printf(
- "\nRequest activation for Office2013 using V4 protocol from 192.168.1.5:1688\n"
- "\t%s -l O15 -4 192.168.1.5\n"
- "\t%s -l O15 -4 192.168.1.5:1688\n\n"
-
- "Request activation for Windows Server 2012 using V4 protocol from localhost:1688\n"
- "\t%s -4 -l Windows -k 8665cb71-468c-4aa3-a337-cb9bc9d5eaac\n"
- "\t%s -4 -l 2012\n"
- "\t%s -4 -l 2012 [::1]:1688\n"
- "\t%s -4 -l 12 127.0.0.2:1688\n\n"
-
- "Send 100,000 requests to localhost:1688\n"
- "\t%s -n 100000 -l Office2010\n\n"
-
- "Request Activation for Windows 8 from 10.0.0.1:4711 and pretend to be Steve Ballmer\n"
- "\t%s -l Windows8 -w steveb1.redmond.microsoft.com 10.0.0.1:4711\n\n",
- programName, programName, programName, programName, programName, programName, programName, programName
- );
-
- exit(0);
-}
-
-
-#else // NO_HELP
-
-
-__noreturn static void clientUsage(const char* const programName)
-{
- errorout("Incorrect parameter specified.\n");
- exit(!0);
-}
-
-
-#endif // NO_HELP
-
-
-static BOOL findLicensePackByName(const char* const name, LicensePack* const lp)
-{
- // Try to find a package in the short list first
-
- LicensePack *licensePack;
- for (licensePack = (LicensePack*)&LicensePackList; licensePack->names; licensePack ++)
- {
- const char *currentName;
- for (currentName = licensePack->names; *currentName; currentName += strlen(currentName) + 1)
- {
- if (!strcasecmp(name, currentName))
- {
- *lp = *licensePack;
- return TRUE;
- }
- }
- }
-
- #if defined(NO_BASIC_PRODUCT_LIST) || defined(NO_EXTENDED_PRODUCT_LIST)
-
- return FALSE;
-
- #else // Both Lists are available
-
- // search extended product list
-
- uint8_t items = getExtendedProductListSize();
- unsigned int index;
-
- if (stringToInt(name, 1, items, &index))
- {
- index--;
- }
- else
- {
- for (index = 0; index < items; index++)
- {
- if (!strcasecmp(ExtendedProductList[index].name, name)) break;
- }
-
- if (index >= items) return FALSE;
- }
-
- lp->AppID = &AppList[ExtendedProductList[index].AppIndex].guid;
- lp->KMSID = ProductList[ExtendedProductList[index].KmsIndex].guid;
- lp->ActID = ExtendedProductList[index].guid;
- lp->N_Policy = ProductList[ExtendedProductList[index].KmsIndex].KMS_PARAM_REQUIREDCOUNT;
- lp->kmsVersionMajor = ProductList[ExtendedProductList[index].KmsIndex].KMS_PARAM_MAJOR;
-
- return TRUE;
-
- #endif // Both Lists are available
-}
-
-static const char* const client_optstring = "+N:B:i:l:a:s:k:c:w:r:n:t:g:G:o:pPTv456mexd";
-
-
-//First pass. We handle only "-l". Since -a -k -s -4 -5 and -6 are exceptions to -l, we process -l first
-static void parseCommandLinePass1(const int argc, CARGV argv)
-{
- int o;
- optReset();
-
- for (opterr = 0; ( o = getopt(argc, (char* const*)argv, client_optstring) ) > 0; ) switch (o)
- {
- case 'l': // Set "License Pack" and protocol version (e.g. Windows8, Office2013v5, ...)
-
- if (!findLicensePackByName(optarg, &ActiveLicensePack))
- {
- errorout("Invalid client application. \"%s\" is not valid for -l.\n\n", optarg);
- #ifndef NO_HELP
- showProducts(&errorout);
- #endif // !NO_HELP
- }
-
- break;
-
- default:
- break;
- }
-}
-
-
-// Second Pass. Handle all options except "-l"
-static void parseCommandLinePass2(const char *const programName, const int argc, CARGV argv)
-{
- int o;
- optReset();
-
- for (opterr = 0; ( o = getopt(argc, (char* const*)argv, client_optstring) ) > 0; ) switch (o)
- {
- #ifndef NO_HELP
-
- case 'e': // Show examples
-
- examples(programName);
- break;
-
- case 'x': // Show Apps
-
- showProducts(&printf);
- break;
-
- #endif // NO_HELP
-
-# ifndef NO_DNS
-
- case 'P':
-
- NoSrvRecordPriority = TRUE;
- break;
-
-# endif // NO_DNS
-
- case 'G':
-
- incompatibleOptions |= VLMCS_OPTION_GRAB_INI;
- fn_ini_client = optarg;
- break;
-
-# ifndef USE_MSRPC
-
- case 'N':
- if (!getArgumentBool(&UseRpcNDR64, optarg)) clientUsage(programName);
- break;
-
- case 'B':
- if (!getArgumentBool(&UseRpcBTFN, optarg)) clientUsage(programName);
- break;
-
- case 'i':
-
- switch(getOptionArgumentInt(o, 4, 6))
- {
- case 4:
- AddressFamily = AF_INET;
- break;
- case 6:
- AddressFamily = AF_INET6;
- break;
- default:
- errorout("IPv5 does not exist.\n");
- exit(!0);
- break;
- }
-
- break;
-
- case 'p': // Multiplexed RPC
-
- UseMultiplexedRpc = FALSE;
- break;
-
-# endif // USE_MSRPC
-
- case 'n': // Fixed number of Requests (regardless, whether they are required)
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- FixedRequests = getOptionArgumentInt(o, 1, INT_MAX);
- break;
-
- case 'r': // Fake minimum required client count
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- ActiveLicensePack.N_Policy = getOptionArgumentInt(o, 1, INT_MAX);
- break;
-
- case 'c': // use a specific client GUID
-
- // If using a constant Client ID, send only one request unless /N= explicitly specified
- if (!FixedRequests) FixedRequests = 1;
-
- CMID = optarg;
- break;
-
- case 'o': // use a specific previous client GUID
-
- CMID_prev = optarg;
- break;
-
- case 'a': // Set specific App Id
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- ActiveLicensePack.AppID = (GUID*)vlmcsd_malloc(sizeof(GUID));
-
- string2UuidOrExit(optarg, (GUID*)ActiveLicensePack.AppID);
- break;
-
- case 'g': // Set custom "grace" time in minutes (default 30 days)
-
- BindingExpiration = getOptionArgumentInt(o, 0, INT_MAX);
- break;
-
- case 's': // Set specfic SKU ID
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- string2UuidOrExit(optarg, &ActiveLicensePack.ActID);
- break;
-
- case 'k': // Set specific KMS ID
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- string2UuidOrExit(optarg, &ActiveLicensePack.KMSID);
- break;
-
- case '4': // Force V4 protocol
- case '5': // Force V5 protocol
- case '6': // Force V5 protocol
-
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- ActiveLicensePack.kmsVersionMajor = o - 0x30;
- break;
-
- case 'd': // Don't use DNS names
-
- dnsnames = FALSE;
- break;
-
- case 'v': // Be verbose
-
- verbose = TRUE;
- break;
-
- case 'm': // Pretend to be a virtual machine
-
- VMInfo = TRUE;
- break;
-
- case 'w': // WorkstationName (max. 63 chars)
-
- WorkstationName = optarg;
-
- if (strlen(WorkstationName) > 63)
- {
- errorout("\007WARNING! Truncating Workstation name to 63 characters (%s).\n", WorkstationName);
- }
-
- break;
-
- case 't':
-
- LicenseStatus = getOptionArgumentInt(o, 0, 6) & 0xff;
- break;
-
-# ifndef USE_MSRPC
-
- case 'T':
-
- ReconnectForEachRequest = TRUE;
- break;
-
-# endif // USE_MSRPC
-
- case 'l':
- incompatibleOptions |= VLMCS_OPTION_NO_GRAB_INI;
- break;
-
- default:
- clientUsage(programName);
- }
- if ((incompatibleOptions & (VLMCS_OPTION_NO_GRAB_INI | VLMCS_OPTION_GRAB_INI)) == (VLMCS_OPTION_NO_GRAB_INI | VLMCS_OPTION_GRAB_INI))
- clientUsage(programName);
-}
-
-
-/*
- * Compares 2 GUIDs where one is host-endian and the other is little-endian (network byte order)
- */
-int_fast8_t IsEqualGuidLEHE(const GUID* const guid1, const GUID* const guid2)
-{
- GUID tempGuid;
- LEGUID(&tempGuid, guid2);
- return IsEqualGUID(guid1, &tempGuid);
-}
-
-
-#ifndef USE_MSRPC
-static void checkRpcLevel(const REQUEST* request, RESPONSE* response)
-{
- if (!RpcFlags.HasNDR32)
- errorout("\nWARNING: Server's RPC protocol does not support NDR32.\n");
-
- if (UseRpcBTFN && UseRpcNDR64 && RpcFlags.HasNDR64 && !RpcFlags.HasBTFN)
- errorout("\nWARNING: Server's RPC protocol has NDR64 but no BTFN.\n");
-
- if (!IsEqualGuidLEHE(&request->KMSID, &ProductList[15].guid) && UseRpcBTFN && !RpcFlags.HasBTFN)
- errorout("\nWARNING: A server with pre-Vista RPC activated a product other than Office 2010.\n");
-}
-#endif // USE_MSRPC
-
-
-static void displayResponse(const RESPONSE_RESULT result, const REQUEST* request, RESPONSE* response, BYTE *hwid)
-{
- fflush(stdout);
-
- if (!result.RpcOK) errorout("\n\007ERROR: Non-Zero RPC result code.\n");
- if (!result.DecryptSuccess) errorout("\n\007ERROR: Decryption of V5/V6 response failed.\n");
- if (!result.IVsOK) errorout("\n\007ERROR: AES CBC initialization vectors (IVs) of request and response do not match.\n");
- if (!result.PidLengthOK) errorout("\n\007ERROR: The length of the PID is not valid.\n");
- if (!result.HashOK) errorout("\n\007ERROR: Computed hash does not match hash in response.\n");
- if (!result.ClientMachineIDOK) errorout("\n\007ERROR: Client machine GUIDs of request and response do not match.\n");
- if (!result.TimeStampOK) errorout("\n\007ERROR: Time stamps of request and response do not match.\n");
- if (!result.VersionOK) errorout("\n\007ERROR: Protocol versions of request and response do not match.\n");
- if (!result.HmacSha256OK) errorout("\n\007ERROR: Keyed-Hash Message Authentication Code (HMAC) is incorrect.\n");
- if (!result.IVnotSuspicious) errorout("\nWARNING: Response uses an IV following KMSv5 rules in KMSv6 protocol.\n");
-
- if (result.effectiveResponseSize != result.correctResponseSize)
- {
- errorout("\n\007WARNING: Size of RPC payload (KMS Message) should be %u but is %u.", result.correctResponseSize, result.effectiveResponseSize);
- }
-
-# ifndef USE_MSRPC
- checkRpcLevel(request, response);
-# endif // USE_MSRPC
-
- if (!result.DecryptSuccess) return; // Makes no sense to display anything
-
- char ePID[3 * PID_BUFFER_SIZE];
- if (!ucs2_to_utf8(response->KmsPID, ePID, PID_BUFFER_SIZE, 3 * PID_BUFFER_SIZE))
- {
- memset(ePID + 3 * PID_BUFFER_SIZE - 3, 0, 3);
- }
-
- // Read KMSPID from Response
- if (!verbose)
- {
- printf(" -> %s", ePID);
-
- if (LE16(response->MajorVer) > 5)
- {
-# ifndef _WIN32
- printf(" (%016llX)", (unsigned long long)BE64(*(uint64_t*)hwid));
-# else // _WIN32
- printf(" (%016I64X)", (unsigned long long)BE64(*(uint64_t*)hwid));
-# endif // _WIN32
- }
-
- printf("\n");
- }
- else
- {
- printf(
- "\n\nResponse from KMS server\n========================\n\n"
- "Size of KMS Response : %u (0x%x)\n", result.effectiveResponseSize, result.effectiveResponseSize
- );
-
- logResponseVerbose(ePID, hwid, response, &printf);
- printf("\n");
- }
-}
-
-
-static void connectRpc(RpcCtx *s)
-{
-# ifdef NO_DNS
-
- *s = connectToAddress(RemoteAddr, AddressFamily, FALSE);
- if (*s == INVALID_RPCCTX)
- {
- errorout("Fatal: Could not connect to %s\n", RemoteAddr);
- exit(!0);
- }
-
- if (verbose)
- printf("\nPerforming RPC bind ...\n");
-
- if (rpcBindClient(*s, verbose))
- {
- errorout("Fatal: Could not bind RPC\n");
- exit(!0);
- }
-
- if (verbose) printf("... successful\n");
-
-# else // DNS
-
- static kms_server_dns_ptr* serverlist = NULL;
- static int numServers = 0;
- //static int_fast8_t ServerListAlreadyPrinted = FALSE;
- int i;
-
- if (!strcmp(RemoteAddr, "-") || *RemoteAddr == '.') // Get KMS server via DNS SRV record
- {
- if (!serverlist)
- numServers = getKmsServerList(&serverlist, RemoteAddr);
-
- if (numServers < 1)
- {
- errorout("Fatal: No KMS servers found\n");
- exit(!0);
- }
-
- if (!NoSrvRecordPriority) sortSrvRecords(serverlist, numServers);
-
- if (verbose /*&& !ServerListAlreadyPrinted*/)
- {
- for (i = 0; i < numServers; i++)
- {
- printf(
- "Found %-40s (priority: %hu, weight: %hu, randomized weight: %i)\n",
- serverlist[i]->serverName,
- serverlist[i]->priority, serverlist[i]->weight,
- NoSrvRecordPriority ? 0 : serverlist[i]->random_weight
- );
- }
-
- printf("\n");
- //ServerListAlreadyPrinted = TRUE;
- }
- }
- else // Just use the server supplied on the command line
- {
- if (!serverlist)
- {
- serverlist = (kms_server_dns_ptr*)vlmcsd_malloc(sizeof(kms_server_dns_ptr));
- *serverlist = (kms_server_dns_ptr)vlmcsd_malloc(sizeof(kms_server_dns_t));
-
- numServers = 1;
- strncpy((*serverlist)->serverName, RemoteAddr, sizeof((*serverlist)->serverName));
- }
- }
-
- for (i = 0; i < numServers; i++)
- {
- *s = connectToAddress(serverlist[i]->serverName, AddressFamily, (*RemoteAddr == '.' || *RemoteAddr == '-'));
-
- if (*s == INVALID_RPCCTX) continue;
-
- if (verbose)
- printf("\nPerforming RPC bind ...\n");
-
- if (rpcBindClient(*s, verbose))
- {
- errorout("Warning: Could not bind RPC\n");
- continue;
- }
-
- if (verbose) printf("... successful\n");
-
- return;
- }
-
- errorout("Fatal: Could not connect to any KMS server\n");
- exit(!0);
-
-# endif // DNS
-}
-
-
-static int SendActivationRequest(const RpcCtx sock, RESPONSE *baseResponse, REQUEST *baseRequest, RESPONSE_RESULT *result, BYTE *const hwid)
-{
- size_t requestSize, responseSize;
- BYTE *request, *response;
- int status;
-
- result->mask = 0;
-
- if (LE16(baseRequest->MajorVer) == 4)
- request = CreateRequestV4(&requestSize, baseRequest);
- else
- request = CreateRequestV6(&requestSize, baseRequest);
-
- if (!(status = rpcSendRequest(sock, request, requestSize, &response, &responseSize)))
- {
- if (LE16(((RESPONSE*)(response))->MajorVer) == 4)
- {
- RESPONSE_V4 response_v4;
- *result = DecryptResponseV4(&response_v4, responseSize, response, request);
- memcpy(baseResponse, &response_v4.ResponseBase, sizeof(RESPONSE));
- }
- else
- {
- RESPONSE_V6 response_v6;
- *result = DecryptResponseV6(&response_v6, responseSize, response, request, hwid);
- memcpy(baseResponse, &response_v6.ResponseBase, sizeof(RESPONSE));
- }
-
- result->RpcOK = TRUE;
- }
-
- if (response) free(response);
- free(request);
- return status;
-}
-
-
-static int sendRequest(RpcCtx *const s, REQUEST *const request, RESPONSE *const response, hwid_t hwid, RESPONSE_RESULT *const result)
-{
- CreateRequestBase(request);
-
- if (*s == INVALID_RPCCTX )
- connectRpc(s);
- else
- {
- // Check for lame KMS emulators that close the socket after each request
- int_fast8_t disconnected = isDisconnected(*s);
-
- if (disconnected)
- errorout("\nWarning: Server closed RPC connection (probably non-multitasked KMS emulator)\n");
-
- if (ReconnectForEachRequest || disconnected)
- {
- closeRpc(*s);
- connectRpc(s);
- }
- }
-
- printf("Sending activation request (KMS V%u) ", ActiveLicensePack.kmsVersionMajor);
- fflush(stdout);
-
- return SendActivationRequest(*s, response, request, result, hwid);
-}
-
-
-static void displayRequestError(RpcCtx *const s, const int status, const int currentRequest, const int totalRequests)
-{
- errorout("\nError 0x%08X while sending request %u of %u\n", status, currentRequest, RequestsToGo + totalRequests);
-
- switch(status)
- {
- case 0xC004F042: // not licensed
- errorout("The server refused to activate the requested product\n");
- break;
-
- case 0x8007000D: // e.g. v6 protocol on a v5 server
- errorout("The server didn't understand the request\n");
- break;
-
- case 1:
- errorout("An RPC protocol error has occured\n");
- closeRpc(*s);
- connectRpc(s);
- break;
-
- default:
- break;
- }
-}
-
-
-static void newIniBackupFile(const char* const restrict fname)
-{
- FILE *restrict f = fopen(fname, "wb");
-
- if (!f)
- {
- errorout("Fatal: Cannot create %s: %s\n", fname, strerror(errno));
- exit(!0);
- }
-
- if (fclose(f))
- {
- errorout("Fatal: Cannot write to %s: %s\n", fname, strerror(errno));
- unlink(fname);
- exit(!0);
- }
-}
-
-
-static void updateIniFile(iniFileEpidLines* const restrict lines)
-{
- int_fast8_t lineWritten[_countof(*lines)];
- struct stat statbuf;
- uint_fast8_t i;
- int_fast8_t iniFileExistedBefore = TRUE;
- unsigned int lineNumber;
-
- memset(lineWritten, FALSE, sizeof(lineWritten));
-
- char* restrict fn_bak = (char*)vlmcsd_malloc(strlen(fn_ini_client) + 2);
-
- strcpy(fn_bak, fn_ini_client);
- strcat(fn_bak, "~");
-
- if (stat(fn_ini_client, &statbuf))
- {
- if (errno != ENOENT)
- {
- errorout("Fatal: %s: %s\n", fn_ini_client, strerror(errno));
- exit(!0);
- }
- else
- {
- iniFileExistedBefore = FALSE;
- newIniBackupFile(fn_bak);
- }
- }
- else
- {
- unlink(fn_bak); // Required for Windows. Most Unix systems don't need it.
- if (rename(fn_ini_client, fn_bak))
- {
- errorout("Fatal: Cannot create %s: %s\n", fn_bak, strerror(errno));
- exit(!0);
- }
- }
-
- printf("\n%s file %s\n", iniFileExistedBefore ? "Updating" : "Creating", fn_ini_client);
-
- FILE *restrict in, *restrict out;
-
- in = fopen(fn_bak, "rb");
-
- if (!in)
- {
- errorout("Fatal: Cannot open %s: %s\n", fn_bak, strerror(errno));
- exit(!0);
- }
-
- out = fopen(fn_ini_client, "wb");
-
- if (!out)
- {
- errorout("Fatal: Cannot create %s: %s\n", fn_ini_client, strerror(errno));
- exit(!0);
- }
-
- char sourceLine[256];
-
- for (lineNumber = 1; fgets(sourceLine, sizeof(sourceLine), in); lineNumber++)
- {
- for (i = 0; i < _countof(*lines); i++)
- {
- if (*(*lines)[i] && !strncasecmp(sourceLine, (*lines)[i], GUID_STRING_LENGTH))
- {
- if (lineWritten[i]) break;
-
- fprintf(out, "%s", (*lines)[i]);
- printf("line %2i: %s", lineNumber, (*lines)[i]);
- lineWritten[i] = TRUE;
- break;
- }
- }
-
- if (i >= _countof(*lines))
- {
- fprintf(out, "%s", sourceLine);
- }
- }
-
- if (ferror(in))
- {
- errorout("Fatal: Cannot read from %s: %s\n", fn_bak, strerror(errno));
- exit(!0);
- }
-
- fclose(in);
-
- for (i = 0; i < _countof(*lines); i++)
- {
- if (!lineWritten[i] && *(*lines)[i])
- {
- fprintf(out, "%s", (*lines)[i]);
- printf("line %2i: %s", lineNumber + i, (*lines)[i]);
- }
- }
-
- if (fclose(out))
- {
- errorout("Fatal: Cannot write to %s: %s\n", fn_ini_client, strerror(errno));
- exit(!0);
- }
-
- if (!iniFileExistedBefore) unlink(fn_bak);
-
- free(fn_bak);
-}
-
-static void grabServerData()
-{
- RpcCtx s = INVALID_RPCCTX;
- WORD MajorVer = 6;
- iniFileEpidLines lines;
- int_fast8_t Licenses[_countof(lines)] = { 0, 15, 14 };
- uint_fast8_t i;
- RESPONSE response;
- RESPONSE_RESULT result;
- REQUEST request;
- hwid_t hwid;
- int status;
- size_t len;
-
- for (i = 0; i < _countof(lines); i++) *lines[i] = 0;
-
- for (i = 0; i < _countof(Licenses) && MajorVer > 3; i++)
- {
- ActiveLicensePack = LicensePackList[Licenses[i]];
- ActiveLicensePack.kmsVersionMajor = MajorVer;
- status = sendRequest(&s, &request, &response, hwid, &result);
- printf("%-11s", ActiveLicensePack.names);
-
- if (status)
- {
- displayRequestError(&s, status, i + 7 - MajorVer, 9 - MajorVer);
-
- if (status == 1) break;
-
- if ((status & 0xF0000000) == 0x80000000)
- {
- MajorVer--;
- i--;
- }
-
- continue;
- }
-
- printf("%i of %i", (int)(i + 7 - MajorVer), (int)(9 - MajorVer));
- displayResponse(result, &request, &response, hwid);
-
- char guidBuffer[GUID_STRING_LENGTH + 1];
- char ePID[3 * PID_BUFFER_SIZE];
-
- uuid2StringLE(&request.AppID, guidBuffer);
-
- if (!ucs2_to_utf8(response.KmsPID, ePID, PID_BUFFER_SIZE, 3 * PID_BUFFER_SIZE))
- {
- memset(ePID + 3 * PID_BUFFER_SIZE - 3, 0, 3);
- }
-
- snprintf(lines[i], sizeof(lines[0]), "%s = %s", guidBuffer, ePID);
-
- if (response.MajorVer > 5)
- {
- len = strlen(lines[i]);
- 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]);
- }
-
- len = strlen(lines[i]);
- snprintf(lines[i] + len, sizeof(lines[0]) - len, "\n");
-
- }
-
- if (strcmp(fn_ini_client, "-"))
- {
- updateIniFile(&lines);
- }
- else
- {
- printf("\n");
- for (i = 0; i < _countof(lines); i++) printf("%s", lines[i]);
- }
-}
-
-
-int client_main(const int argc, CARGV argv)
-{
- #if defined(_WIN32) && !defined(USE_MSRPC)
-
- // Windows Sockets must be initialized
-
- WSADATA wsadata;
- int error;
-
- if ((error = WSAStartup(0x0202, &wsadata)))
- {
- printerrorf("Fatal: Could not initialize Windows sockets (Error: %d).\n", error);
- return error;
- }
-
- #endif // _WIN32
-
- #ifdef _NTSERVICE
-
- // We are not a service
- IsNTService = FALSE;
-
- // Set console output page to UTF-8
- // SetConsoleOutputCP(65001);
-
- #endif // _NTSERVICE
-
- randomNumberInit();
- ActiveLicensePack = *LicensePackList; //first license is Windows Vista
-
- parseCommandLinePass1(argc, argv);
-
- int_fast8_t useDefaultHost = FALSE;
-
- if (optind < argc)
- RemoteAddr = argv[optind];
- else
- useDefaultHost = TRUE;
-
- int hostportarg = optind;
-
- if (optind < argc - 1)
- {
- parseCommandLinePass1(argc - hostportarg, argv + hostportarg);
-
- if (optind < argc - hostportarg)
- clientUsage(argv[0]);
- }
-
- parseCommandLinePass2(argv[0], argc, argv);
-
- if (optind < argc - 1)
- parseCommandLinePass2(argv[0], argc - hostportarg, argv + hostportarg);
-
- if (useDefaultHost)
- RemoteAddr = AddressFamily == AF_INET6 ? "::1" : "127.0.0.1";
-
- if (fn_ini_client != NULL)
- grabServerData();
- else
- {
- int requests;
- RpcCtx s = INVALID_RPCCTX;
-
- for (requests = 0, RequestsToGo = ActiveLicensePack.N_Policy - 1; RequestsToGo; requests++)
- {
- RESPONSE response;
- REQUEST request;
- RESPONSE_RESULT result;
- hwid_t hwid;
-
- int status = sendRequest(&s, &request, &response, hwid, &result);
-
- if (FixedRequests) RequestsToGo = FixedRequests - requests - 1;
-
- if (status)
- {
- displayRequestError(&s, status, requests + 1, RequestsToGo + requests + 1);
- if (!FixedRequests) RequestsToGo = 0;
- }
- else
- {
- if (!FixedRequests)
- {
- if (firstRequestSent && ActiveLicensePack.N_Policy - (int)response.Count >= RequestsToGo)
- {
- errorout("\nThe KMS server does not increment it's active clients. Aborting...\n");
- RequestsToGo = 0;
- }
- else
- {
- RequestsToGo = ActiveLicensePack.N_Policy - response.Count;
- if (RequestsToGo < 0) RequestsToGo = 0;
- }
- }
-
- fflush(stderr);
- printf("%i of %i ", requests + 1, RequestsToGo + requests + 1);
- displayResponse(result, &request, &response, hwid);
- firstRequestSent = TRUE;
- }
- }
- }
-
- return 0;
-}
-
-
-// Create Base KMS Client Request
-static void CreateRequestBase(REQUEST *Request)
-{
-
- Request->MinorVer = LE16((WORD)kmsVersionMinor);
- Request->MajorVer = LE16((WORD)ActiveLicensePack.kmsVersionMajor);
- Request->VMInfo = LE32(VMInfo);
- Request->LicenseStatus = LE32(LicenseStatus);
- Request->BindingExpiration = LE32(BindingExpiration);
- LEGUID(&Request->AppID, ActiveLicensePack.AppID);
- LEGUID(&Request->ActID, &ActiveLicensePack.ActID);
- LEGUID(&Request->KMSID, &ActiveLicensePack.KMSID);
-
- getUnixTimeAsFileTime(&Request->ClientTime);
- Request->N_Policy = LE32(ActiveLicensePack.N_Policy);
-
- {
- GUID tempGUID;
-
- if (CMID)
- {
- string2UuidOrExit(CMID, &tempGUID);
- LEGUID(&Request->CMID, &tempGUID);
- }
- else
- {
- get16RandomBytes(&Request->CMID);
-
- // Set reserved UUID bits
- Request->CMID.Data4[0] &= 0x3F;
- Request->CMID.Data4[0] |= 0x80;
-
- // Set UUID type 4 (random UUID)
- Request->CMID.Data3 &= LE16(0xfff);
- Request->CMID.Data3 |= LE16(0x4000);
- }
-
- if (CMID_prev)
- {
- string2UuidOrExit(CMID_prev, &tempGUID);
- LEGUID(&Request->CMID_prev, &tempGUID);
- }
- else
- {
- memset(&Request->CMID_prev, 0, sizeof(Request->CMID_prev));
- }
- }
-
- static const char alphanum[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /*"abcdefghijklmnopqrstuvwxyz" */;
-
- if (WorkstationName)
- {
- utf8_to_ucs2(Request->WorkstationName, WorkstationName, WORKSTATION_NAME_BUFFER, WORKSTATION_NAME_BUFFER * 3);
- }
- else if (dnsnames)
- {
- int len, len2;
- unsigned int index = rand() % _countof(ClientDnsNames.first);
- len = utf8_to_ucs2(Request->WorkstationName, ClientDnsNames.first[index], WORKSTATION_NAME_BUFFER, WORKSTATION_NAME_BUFFER * 3);
-
- index = rand() % _countof(ClientDnsNames.second);
- len2 = utf8_to_ucs2(Request->WorkstationName + len, ClientDnsNames.second[index], WORKSTATION_NAME_BUFFER, WORKSTATION_NAME_BUFFER * 3);
-
- index = rand() % _countof(ClientDnsNames.tld);
- utf8_to_ucs2(Request->WorkstationName + len + len2, ClientDnsNames.tld[index], WORKSTATION_NAME_BUFFER, WORKSTATION_NAME_BUFFER * 3);
- }
- else
- {
- unsigned int size = (rand() % 14) + 1;
- const unsigned char *dummy;
- unsigned int i;
-
- for (i = 0; i < size; i++)
- {
- Request->WorkstationName[i] = utf8_to_ucs2_char((unsigned char*)alphanum + (rand() % (sizeof(alphanum) - 1)), &dummy);
- }
-
- Request->WorkstationName[size] = 0;
- }
-
- //Show Details
- if (verbose)
- {
- printf("\nRequest Parameters\n==================\n\n");
- logRequestVerbose(Request, &printf);
- printf("\n");
- }
-}
-
-
-/* Multi-Call Binary for vlmcs and vlmcsd */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#if MULTI_CALL_BINARY < 1
-#error "Please define MULTI_CALL_BINARY=1 when compiling this file."
-#endif
-
-#include
-#include
-
-#include "vlmcs.h"
-#include "vlmcsd.h"
-#include "types.h"
-#include "shared_globals.h"
-#include "output.h"
-
-#if (defined(_WIN32) || defined(__CYGWIN__))
-#define compare strcasecmp // Best for case-preserving (but otherwise case-insensitive) filesystems
-#else // native Unix
-#define compare strcmp // for case-sensitive filesystems
-#endif // native Unix
-
-int main(int argc, CARGV argv)
-{
- multi_argv = argv;
- multi_argc = argc;
-
- if (!compare(basename((char*)*argv), "vlmcsd"))
- return server_main(argc, argv);
-
- if (!compare(basename((char*)*argv), "vlmcs"))
- return client_main(argc, argv);
-
- #ifdef _WIN32
- if (!compare(basename((char*)*argv), "vlmcsd.exe"))
- return server_main(argc, argv);
-
- if (!compare(basename((char*)*argv), "vlmcs.exe"))
- return client_main(argc, argv);
- #endif // _WIN32
-
- if (argc > 1)
- {
- if (!strcmp((char*)argv[1],"vlmcsd"))
- return server_main(argc - 1, argv + 1);
-
- if (!strcmp((char*)argv[1],"vlmcs"))
- return client_main(argc - 1, argv + 1);
- }
-
- errorout(
- "vlmcsdmulti %s\n\n"
- "Usage:\n"
- "\t%s vlmcsd []\n"
- "\t%s vlmcs []\n\n",
- Version, *argv, *argv
- );
-
- return !0;
-}
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "crypto.h"
-#include "endian.h"
-#include
-
-const BYTE AesKeyV4[] = {
- 0x05, 0x3D, 0x83, 0x07, 0xF9, 0xE5, 0xF0, 0x88, 0xEB, 0x5E, 0xA6, 0x68, 0x6C, 0xF0, 0x37, 0xC7, 0xE4, 0xEF, 0xD2, 0xD6};
-
-const BYTE AesKeyV5[] = {
- 0xCD, 0x7E, 0x79, 0x6F, 0x2A, 0xB2, 0x5D, 0xCB, 0x55, 0xFF, 0xC8, 0xEF, 0x83, 0x64, 0xC4, 0x70 };
-
-const BYTE AesKeyV6[] = {
- 0xA9, 0x4A, 0x41, 0x95, 0xE2, 0x01, 0x43, 0x2D, 0x9B, 0xCB, 0x46, 0x04, 0x05, 0xD8, 0x4A, 0x21 };
-
-static const BYTE SBox[] = {
- 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
- 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
- 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
- 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
- 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
- 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
- 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
- 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
- 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
- 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
- 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
- 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
- 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
- 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
- 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
- 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
- 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
- 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
- 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
- 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
- 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
- 0xB0, 0x54, 0xBB, 0x16
-};
-
-
-void XorBlock(const BYTE *const in, const BYTE *out) // Ensure that this is always 32 bit aligned
-{
- /*UAA64( out, 0 ) ^= UAA64( in, 0 );
- UAA64( out, 1 ) ^= UAA64( in, 1 );*/
-
- uint_fast8_t i;
-
- for (i = 0; i < AES_BLOCK_WORDS; i++)
- {
- ((DWORD*)out)[i] ^= ((DWORD*)in)[i];
- }
-}
-
-#define AddRoundKey(d, rk) XorBlock((const BYTE *)rk, (const BYTE *)d)
-
-#define Mul2(word) (((word & 0x7f7f7f7f) << 1) ^ (((word & 0x80808080) >> 7) * 0x1b))
-#define Mul3(word) (Mul2(word) ^ word)
-#define Mul4(word) (Mul2(Mul2(word)))
-#define Mul8(word) (Mul2(Mul2(Mul2(word))))
-#define Mul9(word) (Mul8(word) ^ word)
-#define MulB(word) (Mul8(word) ^ Mul3(word))
-#define MulD(word) (Mul8(word) ^ Mul4(word) ^ word)
-#define MulE(word) (Mul8(word) ^ Mul4(word) ^ Mul2(word))
-
-//32 bit Galois Multiplication (generates bigger code than Macros)
-/*static DWORD Mul(DWORD x, DWORD y)
-{
- DWORD result = x, yTemp = y, log2;
-
- if (!y) return 0;
-
- for (log2 = 0; yTemp >>= 1; log2++ )
- {
- result = Mul2(result);
- }
-
- return result ^ Mul(x, y - (1 << log2));
-}*/
-
-
-void MixColumnsR(BYTE *restrict state)
-{
- uint_fast8_t i = 0;
- for (; i < AES_BLOCK_WORDS; i++)
- {
- #if defined(_CRYPTO_OPENSSL) && defined(_OPENSSL_SOFTWARE) && defined(_USE_AES_FROM_OPENSSL) //Always byte swap regardless of endianess
- DWORD word = BS32(((DWORD *) state)[i]);
- ((DWORD *) state)[i] = BS32(MulE(word) ^ ROR32(MulB(word), 8) ^ ROR32(MulD(word), 16) ^ ROR32(Mul9(word), 24));
- #else
- DWORD word = LE32(((DWORD *) state)[i]);
- ((DWORD *) state)[i] = LE32(MulE(word) ^ ROR32(MulB(word), 8) ^ ROR32(MulD(word), 16) ^ ROR32(Mul9(word), 24));
- #endif
- }
-}
-
-
-static DWORD SubDword(DWORD v)
-{
- BYTE *b = (BYTE *)&v;
- uint_fast8_t i = 0;
-
- for (; i < sizeof(DWORD); i++) b[i] = SBox[b[i]];
-
- return v;
-}
-
-
-void AesInitKey(AesCtx *Ctx, const BYTE *Key, int_fast8_t IsV6, int RijndaelKeyBytes)
-{
- int RijndaelKeyDwords = RijndaelKeyBytes / sizeof(DWORD);
- Ctx->rounds = (uint_fast8_t)(RijndaelKeyDwords + 6);
-
- static const DWORD RCon[] = {
- 0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
- 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000 };
-
- uint_fast8_t i;
- DWORD temp;
-
- memcpy(Ctx->Key, Key, RijndaelKeyBytes);
-
- for ( i = RijndaelKeyDwords; i < ( Ctx->rounds + 1 ) << 2; i++ )
- {
- temp = Ctx->Key[ i - 1 ];
-
- if ( ( i % RijndaelKeyDwords ) == 0 )
- temp = BE32( SubDword( ROR32( BE32(temp), 24) ) ^ RCon[ i / RijndaelKeyDwords ] );
-
- Ctx->Key[ i ] = Ctx->Key[ i - RijndaelKeyDwords ] ^ temp;
- }
-
- if ( IsV6 )
- {
- BYTE *_p = (BYTE *)Ctx->Key;
-
- _p[ 4 * 16 ] ^= 0x73;
- _p[ 6 * 16 ] ^= 0x09;
- _p[ 8 * 16 ] ^= 0xE4;
- }
-}
-
-
-#if !defined(_CRYPTO_OPENSSL) || !defined(_USE_AES_FROM_OPENSSL) || defined(_OPENSSL_SOFTWARE)
-static void SubBytes(BYTE *block)
-{
- uint_fast8_t i;
-
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- block[i] = SBox[ block[i] ];
-}
-
-
-static void ShiftRows(BYTE *state)
-{
- BYTE bIn[AES_BLOCK_BYTES];
- uint_fast8_t i;
-
- memcpy(bIn, state, AES_BLOCK_BYTES);
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- {
- state[i] = bIn[(i + ((i & 3) << 2)) & 0xf];
- }
-};
-
-
-static void MixColumns(BYTE *state)
-{
- uint_fast8_t i = 0;
- for (; i < AES_BLOCK_WORDS; i++)
- {
- DWORD word = LE32(((DWORD *) state)[i]);
- ((DWORD *) state)[i] = LE32(Mul2(word) ^ ROR32(Mul3(word), 8) ^ ROR32(word, 16) ^ ROR32(word, 24));
- }
-}
-
-
-void AesEncryptBlock(const AesCtx *const Ctx, BYTE *block)
-{
- uint_fast8_t i;
-
- for ( i = 0 ;; i += 4 )
- {
- AddRoundKey(block, &Ctx->Key[ i ]);
- SubBytes(block);
- ShiftRows(block);
-
- if ( i >= ( Ctx->rounds - 1 ) << 2 ) break;
-
- MixColumns(block);
- }
-
- AddRoundKey(block, &Ctx->Key[ Ctx->rounds << 2 ]);
-}
-
-
-void AesCmacV4(BYTE *Message, size_t MessageSize, BYTE *MacOut)
-{
- size_t i;
- BYTE mac[AES_BLOCK_BYTES];
- AesCtx Ctx;
-
- AesInitKey(&Ctx, AesKeyV4, FALSE, V4_KEY_BYTES);
-
- memset(mac, 0, sizeof(mac));
- memset(Message + MessageSize, 0, AES_BLOCK_BYTES);
- Message[MessageSize] = 0x80;
-
- for (i = 0; i <= MessageSize; i += AES_BLOCK_BYTES)
- {
- XorBlock(Message + i, mac);
- AesEncryptBlock(&Ctx, mac);
- }
-
- memcpy(MacOut, mac, AES_BLOCK_BYTES);
-}
-#endif
-
-#if !defined(_CRYPTO_OPENSSL) || !defined(_USE_AES_FROM_OPENSSL)
-
-static const BYTE SBoxR[] = {
- 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,
- 0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
- 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,
- 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
- 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,
- 0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
- 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
- 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
- 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,
- 0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
- 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
- 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
- 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,
- 0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
- 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,
- 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
- 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,
- 0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
- 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,
- 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
- 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
- 0x55, 0x21, 0x0C, 0x7D
-};
-
-
-static void ShiftRowsR(BYTE *state)
-{
- BYTE b[AES_BLOCK_BYTES];
- uint_fast8_t i;
-
- memcpy(b, state, AES_BLOCK_BYTES);
-
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- state[i] = b[(i - ((i & 0x3) << 2)) & 0xf];
-}
-
-
-static void SubBytesR(BYTE *block)
-{
- uint_fast8_t i;
-
- for (i = 0; i < AES_BLOCK_BYTES; i++)
- block[i] = SBoxR[ block[i] ];
-}
-
-
-void AesEncryptCbc(const AesCtx *const Ctx, BYTE *restrict iv, BYTE *restrict data, size_t *restrict len)
-{
- // Pad up to blocksize inclusive
- size_t i;
- uint_fast8_t pad = (~*len & (AES_BLOCK_BYTES - 1)) + 1;
-
- #if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ == 8) // gcc 4.8 memset bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56977
- for (i = 0; i < pad; i++) data[*len + i] = pad;
- #else
- memset(data + *len, pad, pad);
- #endif
- *len += pad;
-
- if ( iv ) XorBlock(iv, data);
- AesEncryptBlock(Ctx, data);
-
- for (i = *len - AES_BLOCK_BYTES; i; i -= AES_BLOCK_BYTES)
- {
- XorBlock(data, data + AES_BLOCK_BYTES);
- data += AES_BLOCK_BYTES;
- AesEncryptBlock(Ctx, data);
- }
-}
-
-
-void AesDecryptBlock(const AesCtx *const Ctx, BYTE *block)
-{
- uint_fast8_t i;
-
- AddRoundKey(block, &Ctx->Key[ Ctx->rounds << 2 ]);
-
- for ( i = ( Ctx->rounds - 1 ) << 2 ;; i -= 4 )
- {
- ShiftRowsR(block);
- SubBytesR(block);
- AddRoundKey(block, &Ctx->Key[ i ]);
-
- if ( i == 0 ) break;
-
- MixColumnsR(block);
- }
-}
-
-
-void AesDecryptCbc(const AesCtx *const Ctx, BYTE *iv, BYTE *data, size_t len)
-{
- BYTE *cc;
-
- for (cc = data + len - AES_BLOCK_BYTES; cc > data; cc -= AES_BLOCK_BYTES)
- {
- AesDecryptBlock(Ctx, cc);
- XorBlock(cc - AES_BLOCK_BYTES, cc);
- }
-
- AesDecryptBlock(Ctx, cc);
- if ( iv ) XorBlock(iv, cc);
-}
-#endif // _CRYPTO_OPENSSL || OPENSSL_VERSION_NUMBER < 0x10000000L
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include
-#include
-#include
-#include
-#include
-#if !defined(_WIN32)
-#include
-#endif
-
-#include "output.h"
-#include "crypto.h"
-#include "endian.h"
-#include "kms.h"
-#include "shared_globals.h"
-#include "helpers.h"
-
-#define FRIENDLY_NAME_WINDOWS "Windows"
-#define FRIENDLY_NAME_OFFICE2010 "Office 2010"
-#define FRIENDLY_NAME_OFFICE2013 "Office"
-
-#ifndef NO_BASIC_PRODUCT_LIST
-// Do not change the order of this list. Append items as necessary
-const KmsIdList ProductList[] = {
- /* 000 */ { { 0x212a64dc, 0x43b1, 0x4d3d, { 0xa3, 0x0c, 0x2f, 0xc6, 0x9d, 0x20, 0x95, 0xc6 } } /*"212a64dc-43b1-4d3d-a30c-2fc69d2095c6"*/, "Vista", EPID_WINDOWS, 4, 25 },
- /* 001 */ { { 0x7fde5219, 0xfbfa, 0x484a, { 0x82, 0xc9, 0x34, 0xd1, 0xad, 0x53, 0xe8, 0x56 } } /*"7fde5219-fbfa-484a-82c9-34d1ad53e856"*/, "Windows 7", EPID_WINDOWS, 4, 25 },
- /* 002 */ { { 0x3c40b358, 0x5948, 0x45af, { 0x92, 0x3b, 0x53, 0xd2, 0x1f, 0xcc, 0x7e, 0x79 } } /*"3c40b358-5948-45af-923b-53d21fcc7e79"*/, "Windows 8 VL", EPID_WINDOWS, 5, 25 },
- /* 003 */ { { 0x5f94a0bb, 0xd5a0, 0x4081, { 0xa6, 0x85, 0x58, 0x19, 0x41, 0x8b, 0x2f, 0xe0 } } /*"5f94a0bb-d5a0-4081-a685-5819418b2fe0"*/, "Windows Preview", EPID_WINDOWS, 6, 25 },
- /* 004 */ { { 0xbbb97b3b, 0x8ca4, 0x4a28, { 0x97, 0x17, 0x89, 0xfa, 0xbd, 0x42, 0xc4, 0xac } } /*"bbb97b3b-8ca4-4a28-9717-89fabd42c4ac"*/, "Windows 8 Retail", EPID_WINDOWS, 5, 25 },
- /* 005 */ { { 0xcb8fc780, 0x2c05, 0x495a, { 0x97, 0x10, 0x85, 0xaf, 0xff, 0xc9, 0x04, 0xd7 } } /*"cb8fc780-2c05-495a-9710-85afffc904d7"*/, "Windows 8.1 VL", EPID_WINDOWS, 6, 25 },
- /* 006 */ { { 0x6d646890, 0x3606, 0x461a, { 0x86, 0xab, 0x59, 0x8b, 0xb8, 0x4a, 0xce, 0x82 } } /*"6d646890-3606-461a-86ab-598bb84ace82"*/, "Windows 8.1 Retail", EPID_WINDOWS, 6, 25 },
- /* 007 */ { { 0x33e156e4, 0xb76f, 0x4a52, { 0x9f, 0x91, 0xf6, 0x41, 0xdd, 0x95, 0xac, 0x48 } } /*"33e156e4-b76f-4a52-9f91-f641dd95ac48"*/, "Windows 2008 A", EPID_WINDOWS, 4, 5 },
- /* 008 */ { { 0x8fe53387, 0x3087, 0x4447, { 0x89, 0x85, 0xf7, 0x51, 0x32, 0x21, 0x5a, 0xc9 } } /*"8fe53387-3087-4447-8985-f75132215ac9"*/, "Windows 2008 B", EPID_WINDOWS, 4, 5 },
- /* 009 */ { { 0x8a21fdf3, 0xcbc5, 0x44eb, { 0x83, 0xf3, 0xfe, 0x28, 0x4e, 0x66, 0x80, 0xa7 } } /*"8a21fdf3-cbc5-44eb-83f3-fe284e6680a7"*/, "Windows 2008 C", EPID_WINDOWS, 4, 5 },
- /* 010 */ { { 0x0fc6ccaf, 0xff0e, 0x4fae, { 0x9d, 0x08, 0x43, 0x70, 0x78, 0x5b, 0xf7, 0xed } } /*"0fc6ccaf-ff0e-4fae-9d08-4370785bf7ed"*/, "Windows 2008 R2 A", EPID_WINDOWS, 4, 5 },
- /* 011 */ { { 0xca87f5b6, 0xcd46, 0x40c0, { 0xb0, 0x6d, 0x8e, 0xcd, 0x57, 0xa4, 0x37, 0x3f } } /*"ca87f5b6-cd46-40c0-b06d-8ecd57a4373f"*/, "Windows 2008 R2 B", EPID_WINDOWS, 4, 5 },
- /* 012 */ { { 0xb2ca2689, 0xa9a8, 0x42d7, { 0x93, 0x8d, 0xcf, 0x8e, 0x9f, 0x20, 0x19, 0x58 } } /*"b2ca2689-a9a8-42d7-938d-cf8e9f201958"*/, "Windows 2008 R2 C", EPID_WINDOWS, 4, 5 },
- /* 013 */ { { 0x8665cb71, 0x468c, 0x4aa3, { 0xa3, 0x37, 0xcb, 0x9b, 0xc9, 0xd5, 0xea, 0xac } } /*"8665cb71-468c-4aa3-a337-cb9bc9d5eaac"*/, "Windows 2012", EPID_WINDOWS, 5, 5 },
- /* 014 */ { { 0x8456EFD3, 0x0C04, 0x4089, { 0x87, 0x40, 0x5b, 0x72, 0x38, 0x53, 0x5a, 0x65 } } /*"8456EFD3-0C04-4089-8740-5B7238535A65"*/, "Windows 2012 R2", EPID_WINDOWS, 6, 5 },
- /* 015 */ { { 0xe85af946, 0x2e25, 0x47b7, { 0x83, 0xe1, 0xbe, 0xbc, 0xeb, 0xea, 0xc6, 0x11 } } /*"e85af946-2e25-47b7-83e1-bebcebeac611"*/, "Office 2010", EPID_OFFICE2010, 4, 5 },
- /* 016 */ { { 0xe6a6f1bf, 0x9d40, 0x40c3, { 0xaa, 0x9f, 0xc7, 0x7b, 0xa2, 0x15, 0x78, 0xc0 } } /*"e6a6f1bf-9d40-40c3-aa9f-c77ba21578c0"*/, "Office 2013", EPID_OFFICE2013, 6, 5 },
- /* 017 */ { { 0x6d5f5270, 0x31ac, 0x433e, { 0xb9, 0x0a, 0x39, 0x89, 0x29, 0x23, 0xc6, 0x57 } } /*"6d5f5270-31ac-433e-b90a-39892923c657"*/, "Windows Server Preview", EPID_WINDOWS, 6, 5 },
- /* 018 */ { { 0x85b5f61b, 0x320b, 0x4be3, { 0x81, 0x4a, 0xb7, 0x6b, 0x2b, 0xfa, 0xfc, 0x82 } } /*"85b5f61b-320b-4be3-814a-b76b2bfafc82"*/, "Office 2016", EPID_OFFICE2013, 6, 5 },
- /* 019 */ { { 0x58e2134f, 0x8e11, 0x4d17, { 0x9c, 0xb2, 0x91, 0x06, 0x9c, 0x15, 0x11, 0x48 } } /*"58e2134f-8e11-4d17-9cb2-91069c151148"*/, "Windows 10 VL", EPID_WINDOWS, 6, 25 },
- /* 020 */ { { 0xe1c51358, 0xfe3e, 0x4203, { 0xa4, 0xa2, 0x3b, 0x6b, 0x20, 0xc9, 0x73, 0x4e } } /*"e1c51358-fe3e-4203-a4a2-3b6b20c9734e"*/, "Windows 10 Retail", EPID_WINDOWS, 6, 25 },
- /* 021 */ { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
-};
-#endif
-
-// Application ID is used by KMS server to count KeyManagementServiceCurrentCount
-// Do not change the order of this list. Append items as necessary
-const KmsIdList AppList[] = {
- /* 000 */ { { 0x55c92734, 0xd682, 0x4d71, { 0x98, 0x3e, 0xd6, 0xec, 0x3f, 0x16, 0x05, 0x9f } } /*"55C92734-D682-4D71-983E-D6EC3F16059F"*/, FRIENDLY_NAME_WINDOWS, EPID_WINDOWS, 0, 0},
- /* 001 */ { { 0x59A52881, 0xa989, 0x479d, { 0xaf, 0x46, 0xf2, 0x75, 0xc6, 0x37, 0x06, 0x63 } } /*"59A52881-A989-479D-AF46-F275C6370663"*/, FRIENDLY_NAME_OFFICE2010, EPID_OFFICE2010, 0, 0},
- /* 002 */ { { 0x0FF1CE15, 0xA989, 0x479D, { 0xaf, 0x46, 0xf2, 0x75, 0xc6, 0x37, 0x06, 0x63 } } /*"0FF1CE15-A989-479D-AF46-F275C6370663"*/, FRIENDLY_NAME_OFFICE2013, EPID_OFFICE2013, 0, 0},
- /* 003 */ { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
-};
-
-#ifndef NO_EXTENDED_PRODUCT_LIST
-const KmsIdList ExtendedProductList [] = {
-
- // Windows Server
-
- { { 0xad2542d4, 0x9154, 0x4c6d, { 0x8a, 0x44, 0x30, 0xf1, 0x1e, 0xe9, 0x69, 0x89, } } /*ad2542d4-9154-4c6d-8a44-30f11ee96989*/, "Windows Server 2008 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008A },
- { { 0x2401e3d0, 0xc50a, 0x4b58, { 0x87, 0xb2, 0x7e, 0x79, 0x4b, 0x7d, 0x26, 0x07, } } /*2401e3d0-c50a-4b58-87b2-7e794b7d2607*/, "Windows Server 2008 Standard V", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008A },
- { { 0x68b6e220, 0xcf09, 0x466b, { 0x92, 0xd3, 0x45, 0xcd, 0x96, 0x4b, 0x95, 0x09, } } /*68b6e220-cf09-466b-92d3-45cd964b9509*/, "Windows Server 2008 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008C },
- { { 0xfd09ef77, 0x5647, 0x4eff, { 0x80, 0x9c, 0xaf, 0x2b, 0x64, 0x65, 0x9a, 0x45, } } /*fd09ef77-5647-4eff-809c-af2b64659a45*/, "Windows Server 2008 Datacenter V", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008C },
- { { 0xc1af4d90, 0xd1bc, 0x44ca, { 0x85, 0xd4, 0x00, 0x3b, 0xa3, 0x3d, 0xb3, 0xb9, } } /*c1af4d90-d1bc-44ca-85d4-003ba33db3b9*/, "Windows Server 2008 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008B },
- { { 0x8198490a, 0xadd0, 0x47b2, { 0xb3, 0xba, 0x31, 0x6b, 0x12, 0xd6, 0x47, 0xb4, } } /*8198490a-add0-47b2-b3ba-316b12d647b4*/, "Windows Server 2008 Enterprise V", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008B },
- { { 0xddfa9f7c, 0xf09e, 0x40b9, { 0x8c, 0x1a, 0xbe, 0x87, 0x7a, 0x9a, 0x7f, 0x4b, } } /*ddfa9f7c-f09e-40b9-8c1a-be877a9a7f4b*/, "Windows Server 2008 Web", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008A },
- { { 0x7afb1156, 0x2c1d, 0x40fc, { 0xb2, 0x60, 0xaa, 0xb7, 0x44, 0x2b, 0x62, 0xfe, } } /*7afb1156-2c1d-40fc-b260-aab7442b62fe*/, "Windows Server 2008 Compute Cluster", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008C },
- { { 0x68531fb9, 0x5511, 0x4989, { 0x97, 0xbe, 0xd1, 0x1a, 0x0f, 0x55, 0x63, 0x3f, } } /*68531fb9-5511-4989-97be-d11a0f55633f*/, "Windows Server 2008 R2 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2A },
- { { 0x7482e61b, 0xc589, 0x4b7f, { 0x8e, 0xcc, 0x46, 0xd4, 0x55, 0xac, 0x3b, 0x87, } } /*7482e61b-c589-4b7f-8ecc-46d455ac3b87*/, "Windows Server 2008 R2 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2C },
- { { 0x620e2b3d, 0x09e7, 0x42fd, { 0x80, 0x2a, 0x17, 0xa1, 0x36, 0x52, 0xfe, 0x7a, } } /*620e2b3d-09e7-42fd-802a-17a13652fe7a*/, "Windows Server 2008 R2 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2B },
- { { 0xa78b8bd9, 0x8017, 0x4df5, { 0xb8, 0x6a, 0x09, 0xf7, 0x56, 0xaf, 0xfa, 0x7c, } } /*a78b8bd9-8017-4df5-b86a-09f756affa7c*/, "Windows Server 2008 R2 Web", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2A },
- { { 0xcda18cf3, 0xc196, 0x46ad, { 0xb2, 0x89, 0x60, 0xc0, 0x72, 0x86, 0x99, 0x94, } } /*cda18cf3-c196-46ad-b289-60c072869994*/, "Windows Server 2008 R2 Compute Cluster", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2008R2C },
- { { 0xd3643d60, 0x0c42, 0x412d, { 0xa7, 0xd6, 0x52, 0xe6, 0x63, 0x53, 0x27, 0xf6, } } /*d3643d60-0c42-412d-a7d6-52e6635327f6*/, "Windows Server 2012 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0xf0f5ec41, 0x0d55, 0x4732, { 0xaf, 0x02, 0x44, 0x0a, 0x44, 0xa3, 0xcf, 0x0f, } } /*f0f5ec41-0d55-4732-af02-440a44a3cf0f*/, "Windows Server 2012 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0x95fd1c83, 0x7df5, 0x494a, { 0xbe, 0x8b, 0x13, 0x00, 0xe1, 0xc9, 0xd1, 0xcd, } } /*95fd1c83-7df5-494a-be8b-1300e1c9d1cd*/, "Windows Server 2012 MultiPoint Premium", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0x7d5486c7, 0xe120, 0x4771, { 0xb7, 0xf1, 0x7b, 0x56, 0xc6, 0xd3, 0x17, 0x0c, } } /*7d5486c7-e120-4771-b7f1-7b56c6d3170c*/, "Windows Server 2012 MultiPoint Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012 },
- { { 0x00091344, 0x1ea4, 0x4f37, { 0xb7, 0x89, 0x01, 0x75, 0x0b, 0xa6, 0x98, 0x8c, } } /*00091344-1ea4-4f37-b789-01750ba6988c*/, "Windows Server 2012 R2 Datacenter", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0xb3ca044e, 0xa358, 0x4d68, { 0x98, 0x83, 0xaa, 0xa2, 0x94, 0x1a, 0xca, 0x99, } } /*b3ca044e-a358-4d68-9883-aaa2941aca99*/, "Windows Server 2012 R2 Standard", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0xb743a2be, 0x68d4, 0x4dd3, { 0xaf, 0x32, 0x92, 0x42, 0x5b, 0x7b, 0xb6, 0x23, } } /*b743a2be-68d4-4dd3-af32-92425b7bb623*/, "Windows Server 2012 R2 Cloud Storage", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0x21db6ba4, 0x9a7b, 0x4a14, { 0x9e, 0x29, 0x64, 0xa6, 0x0c, 0x59, 0x30, 0x1d, } } /*21db6ba4-9a7b-4a14-9e29-64a60c59301d*/, "Windows Server 2012 R2 Essentials", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN2012R2 },
- { { 0xba947c44, 0xd19d, 0x4786, { 0xb6, 0xae, 0x22, 0x77, 0x0b, 0xc9, 0x4c, 0x54, } } /*ba947c44-d19d-4786-b6ae-22770bc94c54*/, "Windows Server 2016 Datacenter Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_SRV_BETA },
-
-
- // Windows 10 Preview
-# ifdef INCLUDE_BETAS
- { { 0x6496e59d, 0x89dc, 0x49eb, { 0xa3, 0x53, 0x09, 0xce, 0xb9, 0x40, 0x48, 0x45, } } /*6496e59d-89dc-49eb-a353-09ceb9404845*/, "Windows 10 Core Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0xa4383e6b, 0xdada, 0x423d, { 0xa4, 0x3d, 0xf2, 0x56, 0x78, 0x42, 0x96, 0x76, } } /*a4383e6b-dada-423d-a43d-f25678429676*/, "Windows 10 Professional Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0xcf59a07b, 0x1a2a, 0x4be0, { 0xbf, 0xe0, 0x42, 0x3b, 0x58, 0x23, 0xe6, 0x63, } } /*cf59a07b-1a2a-4be0-bfe0-423b5823e663*/, "Windows 10 Professional WMC Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0xcde952c7, 0x2f96, 0x4d9d, { 0x8f, 0x2b, 0x2d, 0x34, 0x9f, 0x64, 0xfc, 0x51, } } /*cde952c7-2f96-4d9d-8f2b-2d349f64fc51*/, "Windows 10 Enterprise Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
-# endif
-
-
- // Windows 10
-
- { { 0x73111121, 0x5638, 0x40f6, { 0xbc, 0x11, 0xf1, 0xd7, 0xb0, 0xd6, 0x43, 0x00, } } /*73111121-5638-40f6-bc11-f1d7b0d64300*/, "Windows 10 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL },
- { { 0xe272e3e2, 0x732f, 0x4c65, { 0xa8, 0xf0, 0x48, 0x47, 0x47, 0xd0, 0xd9, 0x47, } } /*e272e3e2-732f-4c65-a8f0-484747d0d947*/, "Windows 10 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x7b51a46c, 0x0c04, 0x4e8f, { 0x9a, 0xf4, 0x84, 0x96, 0xcc, 0xa9, 0x0d, 0x5e, } } /*7b51a46c-0c04-4e8f-9af4-8496cca90d5e*/, "Windows 10 Enterprise LTSB", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x87b838b7, 0x41b6, 0x4590, { 0x83, 0x18, 0x57, 0x97, 0x95, 0x1d, 0x85, 0x29, } } /*87b838b7-41b6-4590-8318-5797951d8529*/, "Windows 10 Enterprise LTSB N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0xe0c42288, 0x980c, 0x4788, { 0xa0, 0x14, 0xc0, 0x80, 0xd2, 0xe1, 0x92, 0x6e, } } /*e0c42288-980c-4788-a014-c080d2e1926e*/, "Windows 10 Education", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x3c102355, 0xd027, 0x42c6, { 0xad, 0x23, 0x2e, 0x7e, 0xf8, 0xa0, 0x25, 0x85, } } /*3c102355-d027-42c6-ad23-2e7ef8a02585*/, "Windows 10 Education N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x2de67392, 0xb7a7, 0x462a, { 0xb1, 0xca, 0x10, 0x8d, 0xd1, 0x89, 0xf5, 0x88, } } /*2de67392-b7a7-462a-b1ca-108dd189f588*/, "Windows 10 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL },
- { { 0xa80b5abf, 0x75ad, 0x428b, { 0xb0, 0x5d, 0xa4, 0x7d, 0x2d, 0xff, 0xee, 0xbf, } } /*a80b5abf-76ad-428b-b05d-a47d2dffeebf*/, "Windows 10 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_VL},
- { { 0x58e97c99, 0xf377, 0x4ef1, { 0x81, 0xd5, 0x4a, 0xd5, 0x52, 0x2b, 0x5f, 0xd8, } } /*58e97c99-f377-4ef1-81d5-4ad5522b5fd8*/, "Windows 10 Home", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
- { { 0x7b9e1751, 0xa8da, 0x4f75, { 0x95, 0x60, 0x5f, 0xad, 0xfe, 0x3d, 0x8e, 0x38, } } /*7b9e1751-a8da-4f75-9560-5fadfe3d8e38*/, "Windows 10 Home N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
- { { 0xcd918a57, 0xa41b, 0x4c82, { 0x8d, 0xce, 0x1a, 0x53, 0x8e, 0x22, 0x1a, 0x83, } } /*cd918a57-a41b-4c82-8dce-1a538e221a83*/, "Windows 10 Home Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
- { { 0xa9107544, 0xf4a0, 0x4053, { 0xa9, 0x6a, 0x14, 0x79, 0xab, 0xde, 0xf9, 0x12, } } /*a9107544-f4a0-4053-a96a-1479abdef912*/, "Windows 10 Home Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN10_RETAIL},
-
-
- // Windows 8.x
-
-# ifdef INCLUDE_BETAS
- { { 0x2B9C337F, 0x7A1D, 0x4271, { 0x90, 0xA3, 0xC6, 0x85, 0x5A, 0x2B, 0x8A, 0x1C, } } /*2B9C337F-7A1D-4271-90A3-C6855A2B8A1C*/, "Windows 8.x Preview", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
- { { 0x631EAD72, 0xA8AB, 0x4DF8, { 0xBB, 0xDF, 0x37, 0x20, 0x29, 0x98, 0x9B, 0xDD, } } /*631EAD72-A8AB-4DF8-BBDF-372029989BDD*/, "Windows 8.x Preview ARM", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN_BETA },
-# endif
- { { 0x81671aaf, 0x79d1, 0x4eb1, { 0xb0, 0x04, 0x8c, 0xbb, 0xe1, 0x73, 0xaf, 0xea, } } /*81671aaf-79d1-4eb1-b004-8cbbe173afea*/, "Windows 8.1 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0x113e705c, 0xfa49, 0x48a4, { 0xbe, 0xea, 0x7d, 0xd8, 0x79, 0xb4, 0x6b, 0x14, } } /*113e705c-fa49-48a4-beea-7dd879b46b14*/, "Windows 8.1 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0x096ce63d, 0x4fac, 0x48a9, { 0x82, 0xa9, 0x61, 0xae, 0x9e, 0x80, 0x0e, 0x5f, } } /*096ce63d-4fac-48a9-82a9-61ae9e800e5f*/, "Windows 8.1 Professional WMC", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xc06b6981, 0xd7fd, 0x4a35, { 0xb7, 0xb4, 0x05, 0x47, 0x42, 0xb7, 0xaf, 0x67, } } /*c06b6981-d7fd-4a35-b7b4-054742b7af67*/, "Windows 8.1 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0x7476d79f, 0x8e48, 0x49b4, { 0xab, 0x63, 0x4d, 0x0b, 0x81, 0x3a, 0x16, 0xe4, } } /*7476d79f-8e48-49b4-ab63-4d0b813a16e4*/, "Windows 8.1 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xfe1c3238, 0x432a, 0x43a1, { 0x8e, 0x25, 0x97, 0xe7, 0xd1, 0xef, 0x10, 0xf3, } } /*fe1c3238-432a-43a1-8e25-97e7d1ef10f3*/, "Windows 8.1 Core", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0x78558a64, 0xdc19, 0x43fe, { 0xa0, 0xd0, 0x80, 0x75, 0xb2, 0xa3, 0x70, 0xa3, } } /*78558a64-dc19-43fe-a0d0-8075b2a370a3*/, "Windows 8.1 Core N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xffee456a, 0xcd87, 0x4390, { 0x8e, 0x07, 0x16, 0x14, 0x6c, 0x67, 0x2f, 0xd0, } } /*ffee456a-cd87-4390-8e07-16146c672fd0*/, "Windows 8.1 Core ARM", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xc72c6a1d, 0xf252, 0x4e7e, { 0xbd, 0xd1, 0x3f, 0xca, 0x34, 0x2a, 0xcb, 0x35, } } /*c72c6a1d-f252-4e7e-bdd1-3fca342acb35*/, "Windows 8.1 Core Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xdb78b74f, 0xef1c, 0x4892, { 0xab, 0xfe, 0x1e, 0x66, 0xb8, 0x23, 0x1d, 0xf6, } } /*db78b74f-ef1c-4892-abfe-1e66b8231df6*/, "Windows 8.1 Core Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xe9942b32, 0x2e55, 0x4197, { 0xb0, 0xbd, 0x5f, 0xf5, 0x8c, 0xba, 0x88, 0x60, } } /*e9942b32-2e55-4197-b0bd-5ff58cba8860*/, "Windows 8.1 Core Connected", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xc6ddecd6, 0x2354, 0x4c19, { 0x90, 0x9b, 0x30, 0x6a, 0x30, 0x58, 0x48, 0x4e, } } /*c6ddecd6-2354-4c19-909b-306a3058484e*/, "Windows 8.1 Core Connected N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xb8f5e3a3, 0xed33, 0x4608, { 0x81, 0xe1, 0x37, 0xd6, 0xc9, 0xdc, 0xfd, 0x9c, } } /*b8f5e3a3-ed33-4608-81e1-37d6c9dcfd9c*/, "Windows 8.1 Core Connected Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xba998212, 0x460a, 0x44db, { 0xbf, 0xb5, 0x71, 0xbf, 0x09, 0xd1, 0xc6, 0x8b, } } /*ba998212-460a-44db-bfb5-71bf09d1c68b*/, "Windows 8.1 Core Connected Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xe58d87b5, 0x8126, 0x4580, { 0x80, 0xfb, 0x86, 0x1b, 0x22, 0xf7, 0x92, 0x96, } } /*e58d87b5-8126-4580-80fb-861b22f79296*/, "Windows 8.1 Professional Student", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xcab491c7, 0xa918, 0x4f60, { 0xb5, 0x02, 0xda, 0xb7, 0x5e, 0x33, 0x4f, 0x40, } } /*cab491c7-a918-4f60-b502-dab75e334f40*/, "Windows 8.1 Professional Student N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_RETAIL },
- { { 0xa00018a3, 0xf20f, 0x4632, { 0xbf, 0x7c, 0x8d, 0xaa, 0x53, 0x51, 0xc9, 0x14, } } /*a00018a3-f20f-4632-bf7c-8daa5351c914*/, "Windows 8 Professional WMC", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0xa98bcd6d, 0x5343, 0x4603, { 0x8a, 0xfe, 0x59, 0x08, 0xe4, 0x61, 0x11, 0x12, } } /*a98bcd6d-5343-4603-8afe-5908e4611112*/, "Windows 8 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0xebf245c1, 0x29a8, 0x4daf, { 0x9c, 0xb1, 0x38, 0xdf, 0xc6, 0x08, 0xa8, 0xc8, } } /*ebf245c1-29a8-4daf-9cb1-38dfc608a8c8*/, "Windows 8 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0x458e1bec, 0x837a, 0x45f6, { 0xb9, 0xd5, 0x92, 0x5e, 0xd5, 0xd2, 0x99, 0xde, } } /*458e1bec-837a-45f6-b9d5-925ed5d299de*/, "Windows 8 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0xe14997e7, 0x800a, 0x4cf7, { 0xad, 0x10, 0xde, 0x4b, 0x45, 0xb5, 0x78, 0xdb, } } /*e14997e7-800a-4cf7-ad10-de4b45b578db*/, "Windows 8 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_VL },
- { { 0xc04ed6bf, 0x55c8, 0x4b47, { 0x9f, 0x8e, 0x5a, 0x1f, 0x31, 0xce, 0xee, 0x60, } } /*c04ed6bf-55c8-4b47-9f8e-5a1f31ceee60*/, "Windows 8 Core", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0x197390a0, 0x65f6, 0x4a95, { 0xbd, 0xc4, 0x55, 0xd5, 0x8a, 0x3b, 0x02, 0x53, } } /*197390a0-65f6-4a95-bdc4-55d58a3b0253*/, "Windows 8 Core N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0x9d5584a2, 0x2d85, 0x419a, { 0x98, 0x2c, 0xa0, 0x08, 0x88, 0xbb, 0x9d, 0xdf, } } /*9d5584a2-2d85-419a-982c-a00888bb9ddf*/, "Windows 8 Core Country Specific", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
- { { 0x8860fcd4, 0xa77b, 0x4a20, { 0x90, 0x45, 0xa1, 0x50, 0xff, 0x11, 0xd6, 0x09, } } /*8860fcd4-a77b-4a20-9045-a150ff11d609*/, "Windows 8 Core Single Language", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN8_RETAIL },
-
-
- // Windows 7
-
- { { 0xae2ee509, 0x1b34, 0x41c0, { 0xac, 0xb7, 0x6d, 0x46, 0x50, 0x16, 0x89, 0x15, } } /*ae2ee509-1b34-41c0-acb7-6d4650168915*/, "Windows 7 Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0x1cb6d605, 0x11b3, 0x4e14, { 0xbb, 0x30, 0xda, 0x91, 0xc8, 0xe3, 0x98, 0x3a, } } /*1cb6d605-11b3-4e14-bb30-da91c8e3983a*/, "Windows 7 Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0xb92e9980, 0xb9d5, 0x4821, { 0x9c, 0x94, 0x14, 0x0f, 0x63, 0x2f, 0x63, 0x12, } } /*b92e9980-b9d5-4821-9c94-140f632f6312*/, "Windows 7 Professional", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0x54a09a0d, 0xd57b, 0x4c10, { 0x8b, 0x69, 0xa8, 0x42, 0xd6, 0x59, 0x0a, 0xd5, } } /*54a09a0d-d57b-4c10-8b69-a842d6590ad5*/, "Windows 7 Professional N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
-
-
- // Windows Vista
-
- { { 0xcfd8ff08, 0xc0d7, 0x452b, { 0x9f, 0x60, 0xef, 0x5c, 0x70, 0xc3, 0x20, 0x94, } } /*cfd8ff08-c0d7-452b-9f60-ef5c70c32094*/, "Windows Vista Enterprise", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
- { { 0xd4f54950, 0x26f2, 0x4fb4, { 0xba, 0x21, 0xff, 0xab, 0x16, 0xaf, 0xca, 0xde, } } /*d4f54950-26f2-4fb4-ba21-ffab16afcade*/, "Windows Vista Enterprise N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
- { { 0x4f3d1606, 0x3fea, 0x4c01, { 0xbe, 0x3c, 0x8d, 0x67, 0x1c, 0x40, 0x1e, 0x3b, } } /*4f3d1606-3fea-4c01-be3c-8d671c401e3b*/, "Windows Vista Business", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
- { { 0x2c682dc2, 0x8b68, 0x4f63, { 0xa1, 0x65, 0xae, 0x29, 0x1d, 0x4c, 0xf1, 0x38, } } /*2c682dc2-8b68-4f63-a165-ae291d4cf138*/, "Windows Vista Business N", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_VISTA },
-
-
- // Windows Embedded
-
- { { 0xaa6dd3aa, 0xc2b4, 0x40e2, { 0xa5, 0x44, 0xa6, 0xbb, 0xb3, 0xf5, 0xc3, 0x95, } } /*aa6dd3aa-c2b4-40e2-a544-a6bbb3f5c395*/, "Windows ThinPC", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0xdb537896, 0x376f, 0x48ae, { 0xa4, 0x92, 0x53, 0xd0, 0x54, 0x77, 0x73, 0xd0, } } /*db537896-376f-48ae-a492-53d0547773d0*/, "Windows Embedded POSReady 7", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN7 },
- { { 0x0ab82d54, 0x47f4, 0x4acb, { 0x81, 0x8c, 0xcc, 0x5b, 0xf0, 0xec, 0xb6, 0x49, } } /*0ab82d54-47f4-4acb-818c-cc5bf0ecb649*/, "Windows Embedded Industry 8.1", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xcd4e2d9f, 0x5059, 0x4a50, { 0xa9, 0x2d, 0x05, 0xd5, 0xbb, 0x12, 0x67, 0xc7, } } /*cd4e2d9f-5059-4a50-a92d-05d5bb1267c7*/, "Windows Embedded Industry E 8.1", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
- { { 0xf7e88590, 0xdfc7, 0x4c78, { 0xbc, 0xcb, 0x6f, 0x38, 0x65, 0xb9, 0x9d, 0x1a, } } /*f7e88590-dfc7-4c78-bccb-6f3865b99d1a*/, "Windows Embedded Industry A 8.1", EPID_WINDOWS, APP_ID_WINDOWS, KMS_ID_WIN81_VL },
-
- // Office 2010
-
- { { 0x8ce7e872, 0x188c, 0x4b98, { 0x9d, 0x90, 0xf8, 0xf9, 0x0b, 0x7a, 0xad, 0x02, } } /*8ce7e872-188c-4b98-9d90-f8f90b7aad02*/, "Office Access 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xcee5d470, 0x6e3b, 0x4fcc, { 0x8c, 0x2b, 0xd1, 0x74, 0x28, 0x56, 0x8a, 0x9f, } } /*cee5d470-6e3b-4fcc-8c2b-d17428568a9f*/, "Office Excel 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x8947d0b8, 0xc33b, 0x43e1, { 0x8c, 0x56, 0x9b, 0x67, 0x4c, 0x05, 0x28, 0x32, } } /*8947d0b8-c33b-43e1-8c56-9b674c052832*/, "Office Groove 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xca6b6639, 0x4ad6, 0x40ae, { 0xa5, 0x75, 0x14, 0xde, 0xe0, 0x7f, 0x64, 0x30, } } /*ca6b6639-4ad6-40ae-a575-14dee07f6430*/, "Office InfoPath 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x09ed9640, 0xf020, 0x400a, { 0xac, 0xd8, 0xd7, 0xd8, 0x67, 0xdf, 0xd9, 0xc2, } } /*09ed9640-f020-400a-acd8-d7d867dfd9c2*/, "Office Mondo 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xef3d4e49, 0xa53d, 0x4d81, { 0xa2, 0xb1, 0x2c, 0xa6, 0xc2, 0x55, 0x6b, 0x2c, } } /*ef3d4e49-a53d-4d81-a2b1-2ca6c2556b2c*/, "Office Mondo 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xab586f5c, 0x5256, 0x4632, { 0x96, 0x2f, 0xfe, 0xfd, 0x8b, 0x49, 0xe6, 0xf4, } } /*ab586f5c-5256-4632-962f-fefd8b49e6f4*/, "Office OneNote 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xecb7c192, 0x73ab, 0x4ded, { 0xac, 0xf4, 0x23, 0x99, 0xb0, 0x95, 0xd0, 0xcc, } } /*ecb7c192-73ab-4ded-acf4-2399b095d0cc*/, "Office OutLook 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x45593b1d, 0xdfb1, 0x4e91, { 0xbb, 0xfb, 0x2d, 0x5d, 0x0c, 0xe2, 0x22, 0x7a, } } /*45593b1d-dfb1-4e91-bbfb-2d5d0ce2227a*/, "Office PowerPoint 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xdf133ff7, 0xbf14, 0x4f95, { 0xaf, 0xe3, 0x7b, 0x48, 0xe7, 0xe3, 0x31, 0xef, } } /*df133ff7-bf14-4f95-afe3-7b48e7e331ef*/, "Office Project Pro 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x5dc7bf61, 0x5ec9, 0x4996, { 0x9c, 0xcb, 0xdf, 0x80, 0x6a, 0x2d, 0x0e, 0xfe, } } /*5dc7bf61-5ec9-4996-9ccb-df806a2d0efe*/, "Office Project Standard 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xb50c4f75, 0x599b, 0x43e8, { 0x8d, 0xcd, 0x10, 0x81, 0xa7, 0x96, 0x72, 0x41, } } /*b50c4f75-599b-43e8-8dcd-1081a7967241*/, "Office Publisher 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x92236105, 0xbb67, 0x494f, { 0x94, 0xc7, 0x7f, 0x7a, 0x60, 0x79, 0x29, 0xbd, } } /*92236105-bb67-494f-94c7-7f7a607929bd*/, "Office Visio Premium 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xe558389c, 0x83c3, 0x4b29, { 0xad, 0xfe, 0x5e, 0x4d, 0x7f, 0x46, 0xc3, 0x58, } } /*e558389c-83c3-4b29-adfe-5e4d7f46c358*/, "Office Visio Pro 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x9ed833ff, 0x4f92, 0x4f36, { 0xb3, 0x70, 0x86, 0x83, 0xa4, 0xf1, 0x32, 0x75, } } /*9ed833ff-4f92-4f36-b370-8683a4f13275*/, "Office Visio Standard 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x2d0882e7, 0xa4e7, 0x423b, { 0x8c, 0xcc, 0x70, 0xd9, 0x1e, 0x01, 0x58, 0xb1, } } /*2d0882e7-a4e7-423b-8ccc-70d91e0158b1*/, "Office Word 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x6f327760, 0x8c5c, 0x417c, { 0x9b, 0x61, 0x83, 0x6a, 0x98, 0x28, 0x7e, 0x0c, } } /*6f327760-8c5c-417c-9b61-836a98287e0c*/, "Office Professional Plus 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0x9da2a678, 0xfb6b, 0x4e67, { 0xab, 0x84, 0x60, 0xdd, 0x6a, 0x9c, 0x81, 0x9a, } } /*9da2a678-fb6b-4e67-ab84-60dd6a9c819a*/, "Office Standard 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
- { { 0xea509e87, 0x07a1, 0x4a45, { 0x9e, 0xdc, 0xeb, 0xa5, 0xa3, 0x9f, 0x36, 0xaf, } } /*ea509e87-07a1-4a45-9edc-eba5a39f36af*/, "Office Small Business Basics 2010", EPID_OFFICE2010, APP_ID_OFFICE2010, KMS_ID_OFFICE2010 },
-
- // Office 2013
-
- { { 0x6ee7622c, 0x18d8, 0x4005, { 0x9f, 0xb7, 0x92, 0xdb, 0x64, 0x4a, 0x27, 0x9b, } } /*6ee7622c-18d8-4005-9fb7-92db644a279b*/, "Office Access 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xf7461d52, 0x7c2b, 0x43b2, { 0x87, 0x44, 0xea, 0x95, 0x8e, 0x0b, 0xd0, 0x9a, } } /*f7461d52-7c2b-43b2-8744-ea958e0bd09a*/, "Office Excel 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xa30b8040, 0xd68a, 0x423f, { 0xb0, 0xb5, 0x9c, 0xe2, 0x92, 0xea, 0x5a, 0x8f, } } /*a30b8040-d68a-423f-b0b5-9ce292ea5a8f*/, "Office InfoPath 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x1b9f11e3, 0xc85c, 0x4e1b, { 0xbb, 0x29, 0x87, 0x9a, 0xd2, 0xc9, 0x09, 0xe3, } } /*1b9f11e3-c85c-4e1b-bb29-879ad2c909e3*/, "Office Lync 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xdc981c6b, 0xfc8e, 0x420f, { 0xaa, 0x43, 0xf8, 0xf3, 0x3e, 0x5c, 0x09, 0x23, } } /*dc981c6b-fc8e-420f-aa43-f8f33e5c0923*/, "Office Mondo 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xefe1f3e6, 0xaea2, 0x4144, { 0xa2, 0x08, 0x32, 0xaa, 0x87, 0x2b, 0x65, 0x45, } } /*efe1f3e6-aea2-4144-a208-32aa872b6545*/, "Office OneNote 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x771c3afa, 0x50c5, 0x443f, { 0xb1, 0x51, 0xff, 0x25, 0x46, 0xd8, 0x63, 0xa0, } } /*771c3afa-50c5-443f-b151-ff2546d863a0*/, "Office OutLook 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x8c762649, 0x97d1, 0x4953, { 0xad, 0x27, 0xb7, 0xe2, 0xc2, 0x5b, 0x97, 0x2e, } } /*8c762649-97d1-4953-ad27-b7e2c25b972e*/, "Office PowerPoint 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x4a5d124a, 0xe620, 0x44ba, { 0xb6, 0xff, 0x65, 0x89, 0x61, 0xb3, 0x3b, 0x9a, } } /*4a5d124a-e620-44ba-b6ff-658961b33b9a*/, "Office Project Pro 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x427a28d1, 0xd17c, 0x4abf, { 0xb7, 0x17, 0x32, 0xc7, 0x80, 0xba, 0x6f, 0x07, } } /*427a28d1-d17c-4abf-b717-32c780ba6f07*/, "Office Project Standard 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0x00c79ff1, 0x6850, 0x443d, { 0xbf, 0x61, 0x71, 0xcd, 0xe0, 0xde, 0x30, 0x5f, } } /*00c79ff1-6850-443d-bf61-71cde0de305f*/, "Office Publisher 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xac4efaf0, 0xf81f, 0x4f61, { 0xbd, 0xf7, 0xea, 0x32, 0xb0, 0x2a, 0xb1, 0x17, } } /*ac4efaf0-f81f-4f61-bdf7-ea32b02ab117*/, "Office Visio Standard 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xe13ac10e, 0x75d0, 0x4aff, { 0xa0, 0xcd, 0x76, 0x49, 0x82, 0xcf, 0x54, 0x1c, } } /*e13ac10e-75d0-4aff-a0cd-764982cf541c*/, "Office Visio Pro 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xd9f5b1c6, 0x5386, 0x495a, { 0x88, 0xf9, 0x9a, 0xd6, 0xb4, 0x1a, 0xc9, 0xb3, } } /*d9f5b1c6-5386-495a-88f9-9ad6b41ac9b3*/, "Office Word 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xb322da9c, 0xa2e2, 0x4058, { 0x9e, 0x4e, 0xf5, 0x9a, 0x69, 0x70, 0xbd, 0x69, } } /*b322da9c-a2e2-4058-9e4e-f59a6970bd69*/, "Office Professional Plus 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
- { { 0xb13afb38, 0xcd79, 0x4ae5, { 0x9f, 0x7f, 0xee, 0xd0, 0x58, 0xd7, 0x50, 0xca, } } /*b13afb38-cd79-4ae5-9f7f-eed058d750ca*/, "Office Standard 2013", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2013 },
-
- // Office 2016
-
- { { 0xd450596f, 0x894d, 0x49e0, { 0x96, 0x6a, 0xfd, 0x39, 0xed, 0x4c, 0x4c, 0x64, } } /*d450596f-894d-49e0-966a-fd39ed4c4c64*/, "Office Professional Plus 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x4f414197, 0x0fc2, 0x4c01, { 0xb6, 0x8a, 0x86, 0xcb, 0xb9, 0xac, 0x25, 0x4c, } } /*4f414197-0fc2-4c01-b68a-86cbb9ac254c*/, "Office Project Pro 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x6bf301c1, 0xb94a, 0x43e9, { 0xba, 0x31, 0xd4, 0x94, 0x59, 0x8c, 0x47, 0xfb, } } /*6bf301c1-b94a-43e9-ba31-d494598c47fb*/, "Office Visio Pro 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x041a06cb, 0xc5b8, 0x4772, { 0x80, 0x9f, 0x41, 0x6d, 0x03, 0xd1, 0x66, 0x54, } } /*041a06cb-c5b8-4772-809f-416d03d16654*/, "Office Publisher 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x67c0fc0c, 0xdeba, 0x401b, { 0xbf, 0x8b, 0x9c, 0x8a, 0xd8, 0x39, 0x58, 0x04, } } /*67c0fc0c-deba-401b-bf8b-9c8ad8395804*/, "Office Access 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x83e04ee1, 0xfa8d, 0x436d, { 0x89, 0x94, 0xd3, 0x1a, 0x86, 0x2c, 0xab, 0x77, } } /*83e04ee1-fa8d-436d-8994-d31a862cab77*/, "Office Skype for Business 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0x9caabccb, 0x61b1, 0x4b4b, { 0x8b, 0xec, 0xd1, 0x0a, 0x3c, 0x3a, 0xc2, 0xce, } } /*9caabccb-61b1-4b4b-8bec-d10a3c3ac2ce*/, "Office Mondo 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xaa2a7821, 0x1827, 0x4c2c, { 0x8f, 0x1d, 0x45, 0x13, 0xa3, 0x4d, 0xda, 0x97, } } /*aa2a7821-1827-4c2c-8f1d-4513a34dda97*/, "Office Visio Standard 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xbb11badf, 0xd8aa, 0x470e, { 0x93, 0x11, 0x20, 0xea, 0xf8, 0x0f, 0xe5, 0xcc, } } /*bb11badf-d8aa-470e-9311-20eaf80fe5cc*/, "Office Word 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xc3e65d36, 0x141f, 0x4d2f, { 0xa3, 0x03, 0xa8, 0x42, 0xee, 0x75, 0x6a, 0x29, } } /*c3e65d36-141f-4d2f-a303-a842ee756a29*/, "Office Excel 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xd70b1bba, 0xb893, 0x4544, { 0x96, 0xe2, 0xb7, 0xa3, 0x18, 0x09, 0x1c, 0x33, } } /*d70b1bba-b893-4544-96e2-b7a318091c33*/, "Office Powerpoint 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xd8cace59, 0x33d2, 0x4ac7, { 0x9b, 0x1b, 0x9b, 0x72, 0x33, 0x9c, 0x51, 0xc8, } } /*d8cace59-33d2-4ac7-9b1b-9b72339c51c8*/, "Office OneNote 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xda7ddabc, 0x3fbe, 0x4447, { 0x9e, 0x01, 0x6a, 0xb7, 0x44, 0x0b, 0x4c, 0xd4, } } /*da7ddabc-3fbe-4447-9e01-6ab7440b4cd4*/, "Office Project Standard 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xdedfa23d, 0x6ed1, 0x45a6, { 0x85, 0xdc, 0x63, 0xca, 0xe0, 0x54, 0x6d, 0xe6, } } /*dedfa23d-6ed1-45a6-85dc-63cae0546de6*/, "Office Standard 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xe914ea6e, 0xa5fa, 0x4439, { 0xa3, 0x94, 0xa9, 0xbb, 0x32, 0x93, 0xca, 0x09, } } /*e914ea6e-a5fa-4439-a394-a9bb3293ca09*/, "Office Mondo R 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
- { { 0xec9d9265, 0x9d1e, 0x4ed0, { 0x83, 0x8a, 0xcd, 0xc2, 0x0f, 0x25, 0x51, 0xa1, } } /*ec9d9265-9d1e-4ed0-838a-cdc20f2551a1*/, "Office Outlook 2016", EPID_OFFICE2013, APP_ID_OFFICE2013, KMS_ID_OFFICE2016 },
-
- // End marker (necessity should be removed when time permits)
-
- { { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }, NULL, NULL, 0, 0 }
-};
-
-
-// necessary because other .c files cannot access _countof()
-__pure ProdListIndex_t getExtendedProductListSize(void)
-{
- return _countof(ExtendedProductList) - 1;
-}
-
-__pure ProdListIndex_t getAppListSize(void)
-{
- return _countof(AppList);
-}
-
-#endif
-
-#ifndef NO_RANDOM_EPID
-// HostType and OSBuild
-static const struct KMSHostOS { uint16_t Type; uint16_t Build; } HostOS[] =
-{
- { 55041, 6002 }, // Windows Server 2008 SP2
- { 55041, 7601 }, // Windows Server 2008 R2 SP1
- { 5426, 9200 }, // Windows Server 2012
- { 6401, 9600 }, // Windows Server 2012 R2
- { 3612, 10240}, // Windows Server 2016
-};
-
-// GroupID and PIDRange
-static const struct PKEYCONFIG { uint16_t GroupID; uint32_t RangeMin; uint32_t RangeMax; } pkeyconfig[] = {
- { 206, 152000000, 191999999 }, // Windows Server 2012 KMS Host pkeyconfig
- { 206, 271000000, 310999999 }, // Windows Server 2012 R2 KMS Host pkeyconfig
- { 96, 199000000, 217999999 }, // Office2010 KMS Host pkeyconfig
- { 206, 234000000, 255999999 }, // Office2013 KMS Host pkeyconfig
-};
-
-// Valid language identifiers to be used in the ePID
-static const uint16_t LcidList[] = {
- 1078, 1052, 1025, 2049, 3073, 4097, 5121, 6145, 7169, 8193, 9217, 10241, 11265, 12289, 13313, 14337, 15361, 16385,
- 1067, 1068, 2092, 1069, 1059, 1093, 5146, 1026, 1027, 1028, 2052, 3076, 4100, 5124, 1050, 4122, 1029, 1030, 1125, 1043, 2067,
- 1033, 2057, 3081, 4105, 5129, 6153, 7177, 8201, 9225, 10249, 11273, 12297, 13321, 1061, 1080, 1065, 1035, 1036, 2060,
- 3084, 4108, 5132, 6156, 1079, 1110, 1031, 2055, 3079, 4103, 5127, 1032, 1095, 1037, 1081, 1038, 1039, 1057, 1040, 2064, 1041, 1099,
- 1087, 1111, 1042, 1088, 1062, 1063, 1071, 1086, 2110, 1100, 1082, 1153, 1102, 1104, 1044, 2068, 1045, 1046, 2070,
- 1094, 1131, 2155, 3179, 1048, 1049, 9275, 4155, 5179, 3131, 1083, 2107, 8251, 6203, 7227, 1103, 2074, 6170, 3098,
- 7194, 1051, 1060, 1034, 2058, 3082, 4106, 5130, 6154, 7178, 8202, 9226, 10250, 11274, 12298, 13322, 14346, 15370, 16394,
- 17418, 18442, 19466, 20490, 1089, 1053, 2077, 1114, 1097, 1092, 1098, 1054, 1074, 1058, 1056, 1091, 2115, 1066, 1106, 1076, 1077
-};
-
-
-#ifdef _PEDANTIC
-uint16_t IsValidLcid(const uint16_t Lcid)
-{
- uint16_t i;
-
- for (i = 0; i < _countof(LcidList); i++)
- {
- if (Lcid == LcidList[i]) return Lcid;
- }
-
- return 0;
-}
-#endif // _PEDANTIC
-#endif // NO_RANDOM_EPID
-
-
-// Unix time is seconds from 1970-01-01. Should be 64 bits to avoid Year 2035 overflow bug.
-// FILETIME is 100 nanoseconds from 1601-01-01. Must be 64 bits.
-void getUnixTimeAsFileTime(FILETIME *const ts)
-{
- int64_t unixtime = (int64_t)time(NULL);
- int64_t *filetime = (int64_t*)ts;
-
- *filetime = LE64( (unixtime + 11644473600LL) * 10000000LL );
-}
-
-__pure int64_t fileTimeToUnixTime(const FILETIME *const ts)
-{
- return LE64( *((const int64_t *const)ts) ) / 10000000LL - 11644473600LL;
-}
-
-
-/*
- * Get's a product name with a GUID in host-endian order.
- * List can be any list defined above.
- */
-const char* getProductNameHE(const GUID *const guid, const KmsIdList *const List, ProdListIndex_t *const i)
-{
- for (*i = 0; List[*i].name != NULL; (*i)++)
- {
- if (IsEqualGUID(guid, &List[*i].guid))
- return List[*i].name;
- }
-
- return "Unknown";
-}
-
-
-/*
- * same as getProductnameHE except GUID is in little-endian (network) order
- */
-const char* getProductNameLE(const GUID *const guid, const KmsIdList *const List, ProdListIndex_t *const i)
-{
- #if __BYTE_ORDER != __LITTLE_ENDIAN
- GUID HeGUID;
- LEGUID(&HeGUID, guid);
- return getProductNameHE(&HeGUID, List, i);
- #else
- return getProductNameHE(guid, List, i);
- #endif
-}
-
-
-#ifndef NO_RANDOM_EPID
-// formats an int with a fixed number of digits with leading zeros (helper for ePID generation)
-static char* itoc(char *const c, const int i, uint_fast8_t digits)
-{
- char formatString[8];
- if (digits > 9) digits = 0;
- strcpy(formatString,"%");
-
- if (digits)
- {
- formatString[1] = '0';
- formatString[2] = digits | 0x30;
- formatString[3] = 0;
- }
-
- strcat(formatString, "u");
- sprintf(c, formatString, i);
- return c;
-}
-
-static int getRandomServerType()
-{
-# ifndef USE_MSRPC
- if (!UseRpcBTFN)
-# endif // USE_MSRPC
- {
- // This isn't possible at all, e.g. KMS host on XP
- return rand() % (int)_countof(HostOS);
- }
-# ifndef USE_MSRPC
- else
- {
- // return 9200/9600/10240 if NDR64 is in use, otherwise 6002/7601
- if (UseRpcNDR64) return (rand() % 3) + 2;
- return (rand() % 2);
- }
-# endif // USE_MSRPC
-}
-
-
-/*
- * Generates a random ePID
- */
-static void generateRandomPid(const int index, char *const szPid, int serverType, int16_t lang)
-{
- int clientApp;
- char numberBuffer[12];
-
- if (serverType < 0 || serverType >= (int)_countof(HostOS))
- {
- serverType = getRandomServerType();
- }
-
- strcpy(szPid, itoc(numberBuffer, HostOS[serverType].Type, 5));
- strcat(szPid, "-");
-
- if (index == 2)
- clientApp = 3;
- else if (index == 1)
- clientApp = 2;
- else
- clientApp = serverType == 3 /*change if HostOS changes*/ ? 1 : 0;
-
- strcat(szPid, itoc(numberBuffer, pkeyconfig[clientApp].GroupID, 5));
- strcat(szPid, "-");
-
- int keyId = (rand32() % (pkeyconfig[clientApp].RangeMax - pkeyconfig[clientApp].RangeMin)) + pkeyconfig[clientApp].RangeMin;
- strcat(szPid, itoc(numberBuffer, keyId / 1000000, 3));
- strcat(szPid, "-");
- strcat(szPid, itoc(numberBuffer, keyId % 1000000, 6));
- strcat(szPid, "-03-");
-
- if (lang < 0) lang = LcidList[rand() % _countof(LcidList)];
- strcat(szPid, itoc(numberBuffer, lang, 0));
- strcat(szPid, "-");
-
- strcat(szPid, itoc(numberBuffer, HostOS[serverType].Build, 0));
- strcat(szPid, ".0000-");
-
-# define minTime ((time_t)1436958000) // Release Date Windows 10 RTM Escrow
-
- time_t maxTime, kmsTime;
- time(&maxTime);
-
- if (maxTime < minTime) // Just in case the system time is < 07/15/2015 1:00 pm
- maxTime = (time_t)BUILD_TIME;
-
- kmsTime = (rand32() % (maxTime - minTime)) + minTime;
-# undef minTime
-
- struct tm *pidTime;
- pidTime = gmtime(&kmsTime);
-
- strcat(szPid, itoc(numberBuffer, pidTime->tm_yday, 3));
- strcat(szPid, itoc(numberBuffer, pidTime->tm_year + 1900, 4));
-}
-
-
-/*
- * Generates random ePIDs and stores them if not already read from ini file.
- * For use with randomization level 1
- */
-void randomPidInit()
-{
- ProdListIndex_t i;
-
- int serverType = getRandomServerType();
- int16_t lang = Lcid ? Lcid : LcidList[rand() % _countof(LcidList)];
-
- for (i = 0; i < _countof(AppList) - 1; i++)
- {
- if (KmsResponseParameters[i].Epid) continue;
-
- char Epid[PID_BUFFER_SIZE];
-
- generateRandomPid(i, Epid, serverType, lang);
- KmsResponseParameters[i].Epid = (const char*)vlmcsd_malloc(strlen(Epid) + 1);
-
- strcpy((char*)KmsResponseParameters[i].Epid, Epid);
-
- #ifndef NO_LOG
- KmsResponseParameters[i].EpidSource = "randomized at program start";
- #endif // NO_LOG
- }
-}
-
-#endif // NO_RANDOM_EPID
-
-
-#ifndef NO_LOG
-/*
- * Logs a Request
- */
-static void logRequest(const REQUEST *const baseRequest)
-{
- const char *productName;
- char clientname[64];
- ProdListIndex_t index;
-
- #ifndef NO_EXTENDED_PRODUCT_LIST
- productName = getProductNameLE(&baseRequest->ActID, ExtendedProductList, &index);
- if (++index >= (int)_countof(ExtendedProductList))
- #endif // NO_EXTENDED_PRODUCT_LIST
- {
- #ifndef NO_BASIC_PRODUCT_LIST
- productName = getProductNameLE(&baseRequest->KMSID, ProductList, &index);
- if (++index >= (int)_countof(ProductList))
- #endif // NO_BASIC_PRODUCT_LIST
- {
- productName = getProductNameLE(&baseRequest->AppID, AppList, &index);
- }
- }
-
- #ifndef NO_VERBOSE_LOG
- if (logverbose)
- {
- logger("<<< Incoming KMS request\n");
- logRequestVerbose(baseRequest, &logger);
- }
- else
- {
- #endif // NO_VERBOSE_LOG
- 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);
- #ifndef NO_VERBOSE_LOG
- }
- #endif // NO_VERBOSE_LOG
-}
-#endif // NO_LOG
-
-
-/*
- * Converts a utf-8 ePID string to UCS-2 and writes it to a RESPONSE struct
- */
-static void getEpidFromString(RESPONSE *const Response, const char *const pid)
-{
- size_t length = utf8_to_ucs2(Response->KmsPID, pid, PID_BUFFER_SIZE, PID_BUFFER_SIZE * 3);
- Response->PIDSize = LE32(((unsigned int )length + 1) << 1);
-}
-
-
-/*
- * get ePID from appropriate source
- */
-static void getEpid(RESPONSE *const baseResponse, const char** EpidSource, const ProdListIndex_t index, BYTE *const HwId)
-{
- const char* pid;
- if (KmsResponseParameters[index].Epid == NULL)
- {
- #ifndef NO_RANDOM_EPID
- if (RandomizationLevel == 2)
- {
- char szPid[PID_BUFFER_SIZE];
- generateRandomPid(index, szPid, -1, Lcid ? Lcid : -1);
- pid = szPid;
-
- #ifndef NO_LOG
- *EpidSource = "randomized on every request";
- #endif // NO_LOG
- }
- else
- #endif // NO_RANDOM_EPID
- {
- pid = AppList[index].pid;
- #ifndef NO_LOG
- *EpidSource = "vlmcsd default";
- #endif // NO_LOG
- }
- }
- else
- {
- pid = KmsResponseParameters[index].Epid;
-
- if (HwId && KmsResponseParameters[index].HwId != NULL)
- memcpy(HwId, KmsResponseParameters[index].HwId, sizeof(((RESPONSE_V6 *)0)->HwId));
-
- #ifndef NO_LOG
- *EpidSource = KmsResponseParameters[index].EpidSource;
- #endif // NO_LOG
- }
- getEpidFromString(baseResponse, pid);
-}
-
-
-#if !defined(NO_LOG) && defined(_PEDANTIC)
-static BOOL CheckVersion4Uuid(const GUID *const guid, const char *const szGuidName)
-{
- if (LE16(guid->Data3) >> 12 != 4 || guid->Data4[0] >> 6 != 2)
- {
- logger("Warning: %s does not conform to version 4 UUID according to RFC 4122\n", szGuidName);
- return FALSE;
- }
- return TRUE;
-}
-
-
-static void CheckRequest(const REQUEST *const Request)
-{
- CheckVersion4Uuid(&Request->CMID, "Client machine ID");
- CheckVersion4Uuid(&Request->AppID, "Application ID");
- CheckVersion4Uuid(&Request->KMSID, "Server SKU ID");
- CheckVersion4Uuid(&Request->ActID, "Client SKU ID");
-
- if (LE32(Request->IsClientVM) > 1)
- logger("Warning: Virtual Machine field in request must be 0 or 1 but is %u\n", LE32(Request->IsClientVM));
-
- if (LE32(Request->LicenseStatus) > 6 )
- logger("Warning: License status must be between 0 and 6 but is %u\n", LE32(Request->LicenseStatus));
-}
-#endif // !defined(NO_LOG) && defined(_PEDANTIC)
-
-
-#ifndef NO_LOG
-/*
- * Logs the Response
- */
-static void logResponse(const RESPONSE *const 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);
-
- #ifndef NO_VERBOSE_LOG
- if (!logverbose)
- {
- #endif // NO_VERBOSE_LOG
- logger("Sending ePID (%s): %s\n", EpidSource, utf8pid);
- #ifndef NO_VERBOSE_LOG
- }
- else
- {
- logger(">>> Sending response, ePID source = %s\n", EpidSource);
- logResponseVerbose(utf8pid, hwId, baseResponse, &logger);
- }
- #endif // NO_VERBOSE_LOG
-
-}
-#endif
-
-
-/*
- * Creates the unencrypted base response
- */
-static BOOL __stdcall CreateResponseBaseCallback(const REQUEST *const baseRequest, RESPONSE *const baseResponse, BYTE *const hwId, const char* const ipstr)
-{
- const char* EpidSource;
- #ifndef NO_LOG
- logRequest(baseRequest);
- #ifdef _PEDANTIC
- CheckRequest(baseRequest);
- #endif // _PEDANTIC
- #endif // NO_LOG
-
- ProdListIndex_t index;
-
- getProductNameLE(&baseRequest->AppID, AppList, &index);
-
- if (index >= _countof(AppList) - 1) index = 0; //default to Windows
-
- getEpid(baseResponse, &EpidSource, index, hwId);
-
- baseResponse->Version = baseRequest->Version;
-
- memcpy(&baseResponse->CMID, &baseRequest->CMID, sizeof(GUID));
- memcpy(&baseResponse->ClientTime, &baseRequest->ClientTime, sizeof(FILETIME));
-
- baseResponse->Count = LE32(LE32(baseRequest->N_Policy) << 1);
- baseResponse->VLActivationInterval = LE32(VLActivationInterval);
- baseResponse->VLRenewalInterval = LE32(VLRenewalInterval);
-
- #ifndef NO_LOG
- logResponse(baseResponse, hwId, EpidSource);
- #endif // NO_LOG
-
- return !0;
-}
-
-RequestCallback_t CreateResponseBase = &CreateResponseBaseCallback;
-
-////TODO: Move to helpers.c
-void get16RandomBytes(void* ptr)
-{
- int i;
- for (i = 0; i < 4; i++) ((DWORD*)ptr)[i] = rand32();
-}
-
-
-/*
- * Creates v4 response
- */
-size_t CreateResponseV4(REQUEST_V4 *const request_v4, BYTE *const responseBuffer, const char* const ipstr)
-{
- RESPONSE_V4* Response = (RESPONSE_V4*)responseBuffer;
-
- if ( !CreateResponseBase(&request_v4->RequestBase, &Response->ResponseBase, NULL, ipstr) ) return 0;
-
- DWORD pidSize = LE32(Response->ResponseBase.PIDSize);
- BYTE* postEpidPtr = responseBuffer + V4_PRE_EPID_SIZE + pidSize;
- memmove(postEpidPtr, &Response->ResponseBase.CMID, V4_POST_EPID_SIZE);
-
- size_t encryptSize = V4_PRE_EPID_SIZE + V4_POST_EPID_SIZE + pidSize;
- AesCmacV4(responseBuffer, encryptSize, responseBuffer + encryptSize);
-
- return encryptSize + sizeof(Response->MAC);
-}
-
-/*
-// Workaround for buggy GCC 4.2/4.3
-#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 4)
-__attribute__((noinline))
-#endif
-__pure static uint64_t TimestampInterval(void *ts)
-{
- return ( GET_UA64LE(ts) / TIME_C1 ) * TIME_C2 + TIME_C3;
-}*/
-
-
-/*
- * Creates the HMAC for v6
- */
-static int_fast8_t CreateV6Hmac(BYTE *const encrypt_start, const size_t encryptSize, int_fast8_t tolerance)
-{
- BYTE hash[32];
-# define halfHashSize (sizeof(hash) >> 1)
- uint64_t timeSlot;
- BYTE *responseEnd = encrypt_start + encryptSize;
-
- // This is the time from the response
- 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.
- // When generating a response tolerance must be 0.
- // If verifying the hash, try tolerance -1, 0 and +1. One of them must match.
-
- timeSlot = LE64( (GET_UA64LE(ft) / TIME_C1 * TIME_C2 + TIME_C3) + (tolerance * TIME_C1) );
-
- // The time slot is hashed with SHA256 so it is not so obvious that it is time
- Sha256((BYTE*) &timeSlot, sizeof(timeSlot), hash);
-
- // The last 16 bytes of the hashed time slot are the actual HMAC key
- if (!Sha256Hmac
- (
- hash + halfHashSize, // Use last 16 bytes of SHA256 as HMAC key
- encrypt_start, // hash only the encrypted part of the v6 response
- encryptSize - sizeof(((RESPONSE_V6*)0)->HMAC), // encryptSize minus the HMAC itself
- hash // use same buffer for resulting hash where the key came from
- ))
- {
- return FALSE;
- }
-
- memcpy(responseEnd - sizeof(((RESPONSE_V6*)0)->HMAC), hash + halfHashSize, halfHashSize);
- return TRUE;
-# undef halfHashSize
-}
-
-
-/*
- * Creates v5 or v6 response
- */
-size_t CreateResponseV6(REQUEST_V6 *restrict request_v6, BYTE *const responseBuffer, const char* const ipstr)
-{
- // The response will be created in a fixed sized struct to
- // avoid unaligned access macros and packed structs on RISC systems
- // which largely increase code size.
- //
- // 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;
-
- #ifdef _DEBUG
- RESPONSE_V6_DEBUG* xxx = (RESPONSE_V6_DEBUG*)responseBuffer;
- #endif
-
- static const BYTE DefaultHwid[8] = { HWID };
- int_fast8_t v6 = LE16(request_v6->MajorVer) > 5;
- AesCtx aesCtx;
-
- AesInitKey(&aesCtx, v6 ? AesKeyV6 : AesKeyV5, v6, AES_KEY_BYTES);
- 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);
-
- if (v6) // V6 specific stuff
- {
- // In v6 a random IV is generated
- Response->Version = request_v6->Version;
- get16RandomBytes(Response->IV);
-
- // pre-fill with default HwId (not required for v5)
- 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));
- }
- 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);
- }
-
- // Xor Random bytes with decrypted request IV
- XorBlock(request_v6->IV, Response->RandomXoredIVs);
-
- // Get the base response
- if ( !CreateResponseBase(&request_v6->RequestBase, baseResponse, Response->HwId, ipstr) ) return 0;
-
- // Convert the fixed sized struct into variable sized
- DWORD pidSize = LE32(baseResponse->PIDSize);
- BYTE* postEpidPtr = responseBuffer + V6_PRE_EPID_SIZE + pidSize;
- size_t post_epid_size = v6 ? V6_POST_EPID_SIZE : V5_POST_EPID_SIZE;
-
- memmove(postEpidPtr, &baseResponse->CMID, post_epid_size);
-
- // number of bytes to encrypt
- size_t encryptSize =
- V6_PRE_EPID_SIZE
- - sizeof(Response->Version)
- + pidSize
- + post_epid_size;
-
- //AesDecryptBlock(&aesCtx, Response->IV);
- if (v6 && !CreateV6Hmac(Response->IV, encryptSize, 0)) return 0;
-
- // Padding auto handled by encryption func
- AesEncryptCbc(&aesCtx, NULL, Response->IV, &encryptSize);
-
- return encryptSize + sizeof(Response->Version);
-}
-
-
-// Create Hashed KMS Client Request Data for KMS Protocol Version 4
-BYTE *CreateRequestV4(size_t *size, const REQUEST* requestBase)
-{
- *size = sizeof(REQUEST_V4);
-
- // Build a proper KMS client request data
- BYTE *request = (BYTE *)vlmcsd_malloc(sizeof(REQUEST_V4));
-
- // Temporary Pointer for access to REQUEST_V4 structure
- REQUEST_V4 *request_v4 = (REQUEST_V4 *)request;
-
- // Set KMS Client Request Base
- memcpy(&request_v4->RequestBase, requestBase, sizeof(REQUEST));
-
- // Generate Hash Signature
- AesCmacV4(request, sizeof(REQUEST), request_v4->MAC);
-
- // Return Request Data
- return request;
-}
-
-
-// Create Encrypted KMS Client Request Data for KMS Protocol Version 6
-BYTE* CreateRequestV6(size_t *size, const REQUEST* requestBase)
-{
- *size = sizeof(REQUEST_V6);
-
- // Temporary Pointer for access to REQUEST_V5 structure
- REQUEST_V6 *request = (REQUEST_V6 *)vlmcsd_malloc(sizeof(REQUEST_V6));
-
- // KMS Protocol Version
- request->Version = requestBase->Version;
-
- // Initialize the IV
- get16RandomBytes(request->IV);
-
- // Set KMS Client Request Base
- memcpy(&request->RequestBase, requestBase, sizeof(REQUEST));
-
- // 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);
-
- // Return Proper Request Data
- return (BYTE*)request;
-}
-
-
-/*
- * Checks whether Length of ePID is valid
- */
-static uint8_t checkPidLength(const RESPONSE *const responseBase)
-{
- unsigned int i;
-
- if (LE32(responseBase->PIDSize) > (PID_BUFFER_SIZE << 1)) return FALSE;
- if (responseBase->KmsPID[(LE32(responseBase->PIDSize) >> 1) - 1]) return FALSE;
-
- for (i = 0; i < (LE32(responseBase->PIDSize) >> 1) - 2; i++)
- {
- if (!responseBase->KmsPID[i]) return FALSE;
- }
-
- return TRUE;
-}
-
-
-/*
- * "Decrypts" a KMS v4 response. Actually just copies to a fixed size buffer
- */
-RESPONSE_RESULT DecryptResponseV4(RESPONSE_V4* response_v4, const int responseSize, BYTE* const rawResponse, const BYTE* const rawRequest)
-{
- int copySize =
- V4_PRE_EPID_SIZE +
- (LE32(((RESPONSE_V4*)rawResponse)->ResponseBase.PIDSize) <= PID_BUFFER_SIZE << 1 ?
- LE32(((RESPONSE_V4*)rawResponse)->ResponseBase.PIDSize) :
- PID_BUFFER_SIZE << 1);
-
- int messageSize = copySize + V4_POST_EPID_SIZE;
-
- memcpy(response_v4, rawResponse, copySize);
- memcpy(&response_v4->ResponseBase.CMID, rawResponse + copySize, responseSize - copySize);
-
- // ensure PID is null terminated
- response_v4->ResponseBase.KmsPID[PID_BUFFER_SIZE-1] = 0;
-
- uint8_t* mac = rawResponse + messageSize;
- AesCmacV4(rawResponse, messageSize, mac);
-
- REQUEST_V4* request_v4 = (REQUEST_V4*)rawRequest;
- RESPONSE_RESULT result;
-
- result.mask = (DWORD)~0;
- result.PidLengthOK = checkPidLength((RESPONSE*)rawResponse);
- result.VersionOK = response_v4->ResponseBase.Version == request_v4->RequestBase.Version;
- result.HashOK = !memcmp(&response_v4->MAC, mac, sizeof(response_v4->MAC));
- result.TimeStampOK = !memcmp(&response_v4->ResponseBase.ClientTime, &request_v4->RequestBase.ClientTime, sizeof(FILETIME));
- result.ClientMachineIDOK = !memcmp(&response_v4->ResponseBase.CMID, &request_v4->RequestBase.CMID, sizeof(GUID));
- result.effectiveResponseSize = responseSize;
- result.correctResponseSize = sizeof(RESPONSE_V4) - sizeof(response_v4->ResponseBase.KmsPID) + LE32(response_v4->ResponseBase.PIDSize);
-
- return result;
-}
-
-
-static RESPONSE_RESULT VerifyResponseV6(RESPONSE_RESULT result, const AesCtx* Ctx, RESPONSE_V6* response_v6, REQUEST_V6* request_v6, BYTE* const rawResponse)
-{
- // Check IVs
- result.IVsOK = !memcmp // In V6 the XoredIV is actually the request IV
- (
- response_v6->XoredIVs,
- request_v6->IV,
- sizeof(response_v6->XoredIVs)
- );
-
- result.IVnotSuspicious = !!memcmp // If IVs are identical, it is obviously an emulator
- (
- request_v6->IV,
- response_v6->IV,
- sizeof(request_v6->IV)
- );
-
- // Check Hmac
- int_fast8_t tolerance;
- BYTE OldHmac[sizeof(response_v6->HMAC)];
-
- result.HmacSha256OK = FALSE;
-
- memcpy // Save received HMAC to compare with calculated HMAC later
- (
- OldHmac,
- response_v6->HMAC,
- sizeof(response_v6->HMAC)
- );
-
- //AesEncryptBlock(Ctx, Response_v6->IV); // CreateV6Hmac needs original IV as received over the network
-
- for (tolerance = -1; tolerance < 2; tolerance++)
- {
- CreateV6Hmac
- (
- rawResponse + sizeof(response_v6->Version), // Pointer to start of the encrypted part of the response
- (size_t)result.correctResponseSize - V6_UNENCRYPTED_SIZE, // size of the encrypted part
- tolerance // tolerance -1, 0, or +1
- );
-
- if
- ((
- result.HmacSha256OK = !memcmp // Compare both HMACs
- (
- OldHmac,
- rawResponse + (size_t)result.correctResponseSize - sizeof(response_v6->HMAC),
- sizeof(OldHmac)
- )
- ))
- {
- break;
- }
- }
- return result;
-}
-
-
-static RESPONSE_RESULT VerifyResponseV5(RESPONSE_RESULT result, REQUEST_V5* request_v5, RESPONSE_V5* response_v5)
-{
- // Check IVs: in V5 (and only v5) request and response IVs must match
- result.IVsOK = !memcmp(request_v5->IV, response_v5->IV, sizeof(request_v5->IV));
-
- // V5 has no Hmac, always set to TRUE
- result.HmacSha256OK = TRUE;
-
- return result;
-}
-
-
-/*
- * Decrypts a KMS v5 or v6 response received from a server.
- * hwid must supply a valid 16 byte buffer for v6. hwid is ignored in v5
- */
-RESPONSE_RESULT DecryptResponseV6(RESPONSE_V6* response_v6, int responseSize, BYTE* const response, const BYTE* const rawRequest, BYTE* hwid)
-{
- RESPONSE_RESULT result;
- result.mask = ~0; // Set all bits in the results mask to 1. Assume success first.
- result.effectiveResponseSize = responseSize;
-
- int copySize1 =
- sizeof(response_v6->Version);
-
- // Decrypt KMS Server Response (encrypted part starts after RequestIV)
- responseSize -= copySize1;
-
- AesCtx Ctx;
- 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);
-
- // Check padding
- BYTE* lastPadByte = response + (size_t)result.effectiveResponseSize - 1;
-
- // Must be from 1 to 16
- if (!*lastPadByte || *lastPadByte > AES_BLOCK_BYTES)
- {
- result.DecryptSuccess = FALSE;
- return result;
- }
-
- // Check if pad bytes are all the same
- BYTE* padByte;
- for (padByte = lastPadByte - *lastPadByte + 1; padByte < lastPadByte; padByte++)
- if (*padByte != *lastPadByte)
- {
- result.DecryptSuccess = FALSE;
- return result;
- }
-
- // Add size of Version, KmsPIDLen and variable size PID
- DWORD pidSize = LE32(((RESPONSE_V6*) response)->ResponseBase.PIDSize);
-
- copySize1 +=
- V6_UNENCRYPTED_SIZE +
- sizeof(response_v6->ResponseBase.PIDSize) +
- (pidSize <= PID_BUFFER_SIZE << 1 ? pidSize : PID_BUFFER_SIZE << 1);
-
- // Copy part 1 of response up to variable sized PID
- memcpy(response_v6, response, copySize1);
-
- // ensure PID is null terminated
- response_v6->ResponseBase.KmsPID[PID_BUFFER_SIZE - 1] = 0;
-
- // Copy part 2
- size_t copySize2 = v6 ? V6_POST_EPID_SIZE : V5_POST_EPID_SIZE;
- memcpy(&response_v6->ResponseBase.CMID, response + copySize1, copySize2);
-
- // Decrypting the response is finished here. Now we check the results for validity
- // A basic client doesn't need the stuff below this comment but we want to use vlmcs
- // as a debug tool for KMS emulators.
-
- REQUEST_V6* request_v6 = (REQUEST_V6*) rawRequest;
- DWORD decryptSize = sizeof(request_v6->IV) + sizeof(request_v6->RequestBase) + sizeof(request_v6->Pad);
-
- AesDecryptCbc(&Ctx, NULL, request_v6->IV, decryptSize);
-
- // Check that all version informations are the same
- result.VersionOK =
- request_v6->Version == response_v6->ResponseBase.Version &&
- request_v6->Version == response_v6->Version &&
- request_v6->Version == request_v6->RequestBase.Version;
-
- // Check Base Request
- result.PidLengthOK = checkPidLength(&((RESPONSE_V6*) response)->ResponseBase);
- result.TimeStampOK = !memcmp(&response_v6->ResponseBase.ClientTime, &request_v6->RequestBase.ClientTime, sizeof(FILETIME));
- 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)];
-
- 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));
-
- // size before encryption (padding not included)
- result.correctResponseSize =
- (v6 ? sizeof(RESPONSE_V6) : sizeof(RESPONSE_V5))
- - sizeof(response_v6->ResponseBase.KmsPID)
- + LE32(response_v6->ResponseBase.PIDSize);
-
- // Version specific stuff
- if (v6)
- {
- // Copy the HwId
- memcpy(hwid, response_v6->HwId, sizeof(response_v6->HwId));
-
- // Verify the V6 specific part of the response
- result = VerifyResponseV6(result, &Ctx, response_v6, request_v6, response);
- }
- else // V5
- {
- // Verify the V5 specific part of the response
- result = VerifyResponseV5(result, request_v6, (RESPONSE_V5*)response_v6);
- }
-
- // padded size after encryption
- result.correctResponseSize += (~(result.correctResponseSize - sizeof(response_v6->ResponseBase.Version)) & 0xf) + 1;
-
- return result;
-}
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "endian.h"
-
-#if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) \
- && defined(BS16) && defined(BS32) && defined(BS64)
-
-#else // ! defined(__BYTE_ORDER)
-
-void PUT_UAA64BE(void *p, unsigned long long v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- _p[ 0 ] = v >> 56;
- _p[ 1 ] = v >> 48;
- _p[ 2 ] = v >> 40;
- _p[ 3 ] = v >> 32;
- _p[ 4 ] = v >> 24;
- _p[ 5 ] = v >> 16;
- _p[ 6 ] = v >> 8;
- _p[ 7 ] = v;
-}
-
-void PUT_UAA32BE(void *p, unsigned int v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- _p[ 0 ] = v >> 24;
- _p[ 1 ] = v >> 16;
- _p[ 2 ] = v >> 8;
- _p[ 3 ] = v;
-}
-
-void PUT_UAA16BE(void *p, unsigned short v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- _p[ 0 ] = v >> 8;
- _p[ 1 ] = v;
-}
-
-
-void PUT_UAA64LE(void *p, unsigned long long v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- _p[ 0 ] = v;
- _p[ 1 ] = v >> 8;
- _p[ 2 ] = v >> 16;
- _p[ 3 ] = v >> 24;
- _p[ 4 ] = v >> 32;
- _p[ 5 ] = v >> 40;
- _p[ 6 ] = v >> 48;
- _p[ 7 ] = v >> 56;
-}
-
-void PUT_UAA32LE(void *p, unsigned int v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- _p[ 0 ] = v;
- _p[ 1 ] = v >> 8;
- _p[ 2 ] = v >> 16;
- _p[ 3 ] = v >> 24;
-}
-
-void PUT_UAA16LE(void *p, unsigned short v, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- _p[ 0 ] = v;
- _p[ 1 ] = v >> 8;
-}
-
-
-unsigned long long GET_UAA64BE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- return
- (unsigned long long)_p[ 0 ] << 56 |
- (unsigned long long)_p[ 1 ] << 48 |
- (unsigned long long)_p[ 2 ] << 40 |
- (unsigned long long)_p[ 3 ] << 32 |
- (unsigned long long)_p[ 4 ] << 24 |
- (unsigned long long)_p[ 5 ] << 16 |
- (unsigned long long)_p[ 6 ] << 8 |
- (unsigned long long)_p[ 7 ];
-
-}
-
-unsigned int GET_UAA32BE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- return
- (unsigned int)_p[ 0 ] << 24 |
- (unsigned int)_p[ 1 ] << 16 |
- (unsigned int)_p[ 2 ] << 8 |
- (unsigned int)_p[ 3 ];
-}
-
-unsigned short GET_UAA16BE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- return
- (unsigned short)_p[ 0 ] << 8 |
- (unsigned short)_p[ 1 ];
-}
-
-
-unsigned long long GET_UAA64LE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned long long *)p)[i];
- return
- (unsigned long long)_p[ 0 ] |
- (unsigned long long)_p[ 1 ] << 8 |
- (unsigned long long)_p[ 2 ] << 16 |
- (unsigned long long)_p[ 3 ] << 24 |
- (unsigned long long)_p[ 4 ] << 32 |
- (unsigned long long)_p[ 5 ] << 40 |
- (unsigned long long)_p[ 6 ] << 48 |
- (unsigned long long)_p[ 7 ] << 56;
-
-}
-
-unsigned int GET_UAA32LE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned int *)p)[i];
- return
- (unsigned int)_p[ 0 ] |
- (unsigned int)_p[ 1 ] << 8 |
- (unsigned int)_p[ 2 ] << 16 |
- (unsigned int)_p[ 3 ] << 24;
-}
-
-unsigned short GET_UAA16LE(void *p, unsigned int i)
-{
- unsigned char *_p = (unsigned char *)&((unsigned short *)p)[i];
- return
- (unsigned short)_p[ 0 ] |
- (unsigned short)_p[ 1 ] << 8;
-}
-
-
-unsigned short BE16(unsigned short x)
-{
- return GET_UAA16BE(&x, 0);
-}
-
-unsigned short LE16(unsigned short x)
-{
- return GET_UAA16LE(&x, 0);
-}
-
-unsigned int BE32(unsigned int x)
-{
- return GET_UAA32BE(&x, 0);
-}
-
-unsigned int LE32(unsigned int x)
-{
- return GET_UAA32LE(&x, 0);
-}
-
-unsigned long long BE64(unsigned long long x)
-{
- return GET_UAA64BE(&x, 0);
-}
-
-inline unsigned long long LE64(unsigned long long x)
-{
- return GET_UAA64LE(&x, 0);
-}
-
-#endif // defined(__BYTE_ORDER)
-#ifndef _DEFAULT_SOURCE
-#define _DEFAULT_SOURCE
-#endif // _DEFAULT_SOURCE
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "output.h"
-#include "shared_globals.h"
-#include "endian.h"
-#include "helpers.h"
-
-#ifndef NO_LOG
-static void vlogger(const char *message, va_list args)
-{
- FILE *log;
-
- #ifdef _NTSERVICE
- if (!IsNTService && logstdout) log = stdout;
- #else
- if (logstdout) log = stdout;
- #endif
- else
- {
- if (fn_log == NULL) return;
-
- #ifndef _WIN32
- if (!strcmp(fn_log, "syslog"))
- {
- openlog("vlmcsd", LOG_CONS | LOG_PID, LOG_USER);
-
- ////PORTABILITY: vsyslog is not in Posix but virtually all Unixes have it
- vsyslog(LOG_INFO, message, args);
-
- closelog();
- return;
- }
- #endif // _WIN32
-
- log = fopen(fn_log, "a");
- if ( !log ) return;
- }
-
- time_t now = time(0);
-
- #ifdef USE_THREADS
- char mbstr[2048];
- #else
- char mbstr[24];
- #endif
-
- strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", localtime(&now));
-
- #ifndef USE_THREADS
-
- fprintf(log, "%s: ", mbstr);
- vfprintf(log, message, args);
- fflush(log);
-
- #else // USE_THREADS
-
- // We write everything to a string before we really log inside the critical section
- // so formatting the output can be concurrent
- strcat(mbstr, ": ");
- int len = strlen(mbstr);
- vsnprintf(mbstr + len, sizeof(mbstr) - len, message, args);
-
- lock_mutex(&logmutex);
- fputs(mbstr, log);
- fflush(log);
- unlock_mutex(&logmutex);
-
- #endif // USE_THREADS
- if (log != stdout) fclose(log);
-}
-
-
-// Always sends to log output
-int logger(const char *const fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- vlogger(fmt, args);
- va_end(args);
- return 0;
-}
-
-#endif //NO_LOG
-
-
-// Output to stderr if it is available or to log otherwise (e.g. if running as daemon/service)
-void printerrorf(const char *const fmt, ...)
-{
- va_list arglist;
-
- va_start(arglist, fmt);
-
- #ifndef NO_LOG
- #ifdef _NTSERVICE
- if (InetdMode || IsNTService)
- #else // !_NTSERVICE
- if (InetdMode)
- #endif // NTSERVIICE
- vlogger(fmt, arglist);
- else
- #endif //NO_LOG
- {
- vfprintf(stderr, fmt, arglist);
- fflush(stderr);
- }
-
- va_end(arglist);
-}
-
-
-// Always output to stderr
-int errorout(const char* fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- int i = vfprintf(stderr, fmt, args);
- va_end(args);
- fflush(stderr);
-
- return i;
-}
-
-
-static const char *LicenseStatusText[] =
-{
- "Unlicensed", "Licensed", "OOB grace", "OOT grace", "Non-Genuine", "Notification", "Extended grace"
-};
-
-
-void uuid2StringLE(const GUID *const guid, char *const string)
-{
- sprintf(string,
- #ifdef _WIN32
- "%08x-%04x-%04x-%04x-%012I64x",
- #else
- "%08x-%04x-%04x-%04x-%012llx",
- #endif
- (unsigned int)LE32( guid->Data1 ),
- (unsigned int)LE16( guid->Data2 ),
- (unsigned int)LE16( guid->Data3 ),
- (unsigned int)BE16( *(uint16_t*)guid->Data4 ),
- (unsigned long long)BE64(*(uint64_t*)(guid->Data4)) & 0xffffffffffffLL
- );
-}
-
-
-void logRequestVerbose(const REQUEST *const Request, const PRINTFUNC p)
-{
- char guidBuffer[GUID_STRING_LENGTH + 1];
- char WorkstationBuffer[3 * WORKSTATION_NAME_BUFFER];
- const char *productName;
- ProdListIndex_t index;
-
- p("Protocol version : %u.%u\n", LE16(Request->MajorVer), LE16(Request->MinorVer));
- p("Client is a virtual machine : %s\n", LE32(Request->VMInfo) ? "Yes" : "No");
- p("Licensing status : %u (%s)\n", (uint32_t)LE32(Request->LicenseStatus), LE32(Request->LicenseStatus) < _countof(LicenseStatusText) ? LicenseStatusText[LE32(Request->LicenseStatus)] : "Unknown");
- p("Remaining time (0 = forever) : %i minutes\n", (uint32_t)LE32(Request->BindingExpiration));
-
- uuid2StringLE(&Request->AppID, guidBuffer);
- productName = getProductNameLE(&Request->AppID, AppList, &index);
- p("Application ID : %s (%s)\n", guidBuffer, productName);
-
- uuid2StringLE(&Request->ActID, guidBuffer);
-
- #ifndef NO_EXTENDED_PRODUCT_LIST
- productName = getProductNameLE(&Request->ActID, ExtendedProductList, &index);
- #else
- productName = "Unknown";
- #endif
-
- p("Activation ID (Product) : %s (%s)\n", guidBuffer, productName);
-
- uuid2StringLE(&Request->KMSID, guidBuffer);
-
- #ifndef NO_BASIC_PRODUCT_LIST
- productName = getProductNameLE(&Request->KMSID, ProductList, &index);
- #else
- productName = "Unknown";
- #endif
-
- p("Key Management Service ID : %s (%s)\n", guidBuffer, productName);
-
- uuid2StringLE(&Request->CMID, guidBuffer);
- p("Client machine ID : %s\n", guidBuffer);
-
- uuid2StringLE(&Request->CMID_prev, guidBuffer);
- p("Previous client machine ID : %s\n", guidBuffer);
-
-
- char mbstr[64];
- time_t st;
- st = fileTimeToUnixTime(&Request->ClientTime);
- strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", gmtime(&st));
- p("Client request timestamp (UTC) : %s\n", mbstr);
-
- ucs2_to_utf8(Request->WorkstationName, WorkstationBuffer, WORKSTATION_NAME_BUFFER, sizeof(WorkstationBuffer));
-
- p("Workstation name : %s\n", WorkstationBuffer);
- 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)
-{
- char guidBuffer[GUID_STRING_LENGTH + 1];
- //SYSTEMTIME st;
-
- p("Protocol version : %u.%u\n", (uint32_t)LE16(response->MajorVer), (uint32_t)LE16(response->MinorVer));
- p("KMS host extended PID : %s\n", ePID);
- if (LE16(response->MajorVer) > 5)
-# ifndef _WIN32
- p("KMS host Hardware ID : %016llX\n", (unsigned long long)BE64(*(uint64_t*)hwid));
-# else // _WIN32
- p("KMS host Hardware ID : %016I64X\n", (unsigned long long)BE64(*(uint64_t*)hwid));
-# endif // WIN32
-
- uuid2StringLE(&response->CMID, guidBuffer);
- p("Client machine ID : %s\n", guidBuffer);
-
- char mbstr[64];
- time_t st;
-
- st = fileTimeToUnixTime(&response->ClientTime);
- strftime(mbstr, sizeof(mbstr), "%Y-%m-%d %X", gmtime(&st));
- p("Client request timestamp (UTC) : %s\n", mbstr);
-
- p("KMS host current active clients : %u\n", (uint32_t)LE32(response->Count));
- p("Renewal interval policy : %u\n", (uint32_t)LE32(response->VLRenewalInterval));
- p("Activation interval policy : %u\n", (uint32_t)LE32(response->VLActivationInterval));
-}
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#include "shared_globals.h"
-
-int global_argc, multi_argc = 0;
-CARGV global_argv, multi_argv = NULL;
-const char *const Version = VERSION;
-DWORD VLActivationInterval = 60 * 2; // 2 hours
-DWORD VLRenewalInterval = 60 * 24 * 7; // 7 days
-int_fast8_t DisconnectImmediately = FALSE;
-const char *const cIPv4 = "IPv4";
-const char *const cIPv6 = "IPv6";
-
-#ifndef USE_MSRPC
-int_fast8_t UseMultiplexedRpc = TRUE;
-int_fast8_t UseRpcNDR64 = TRUE;
-int_fast8_t UseRpcBTFN = TRUE;
-#endif // USE_MSRPC
-
-#ifndef NO_SOCKETS
-const char *defaultport = "1688";
-#endif // NO_SOCKETS
-
-KmsResponseParam_t KmsResponseParameters[MAX_KMSAPPS];
-
-#if !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
-int_fast8_t IsRestarted = FALSE;
-#endif // !defined(NO_SOCKETS) && !defined(NO_SIGHUP) && !defined(_WIN32)
-
-#if !defined(NO_TIMEOUT) && !__minix__
-DWORD ServerTimeout = 30;
-#endif // !defined(NO_TIMEOUT) && !__minix__
-
-#if !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-#ifdef USE_MSRPC
-uint32_t MaxTasks = RPC_C_LISTEN_MAX_CALLS_DEFAULT;
-#else // !USE_MSRPC
-uint32_t MaxTasks = SEM_VALUE_MAX;
-#endif // !USE_MSRPC
-#endif // !defined(NO_LIMIT) && !defined (NO_SOCKETS) && !__minix__
-
-#ifndef NO_LOG
-char *fn_log = NULL;
-int_fast8_t logstdout = 0;
-#ifndef NO_VERBOSE_LOG
-int_fast8_t logverbose = 0;
-#endif // NO_VERBOSE_LOG
-#endif // NO_LOG
-
-#ifndef NO_SOCKETS
-int_fast8_t nodaemon = 0;
-int_fast8_t InetdMode = 0;
-#else
-int_fast8_t nodaemon = 1;
-int_fast8_t InetdMode = 1;
-#endif
-
-#ifndef NO_RANDOM_EPID
-int_fast8_t RandomizationLevel = 1;
-uint16_t Lcid = 0;
-#endif
-
-#ifndef NO_SOCKETS
-SOCKET *SocketList;
-int numsockets = 0;
-
-#if !defined(NO_LIMIT) && !__minix__
-#ifndef _WIN32 // Posix
-sem_t *Semaphore;
-#else // _WIN32
-HANDLE Semaphore;
-#endif // _WIN32
-
-#endif // !defined(NO_LIMIT) && !__minix__
-#endif // NO_SOCKETS
-
-#ifdef _NTSERVICE
-int_fast8_t IsNTService = TRUE;
-int_fast8_t ServiceShutdown = FALSE;
-#endif // _NTSERVICE
-
-#ifndef NO_LOG
-#ifdef USE_THREADS
-#if !defined(_WIN32) && !defined(__CYGWIN__)
-pthread_mutex_t logmutex = PTHREAD_MUTEX_INITIALIZER;
-#else
-CRITICAL_SECTION logmutex;
-#endif // !defined(_WIN32) && !defined(__CYGWIN__)
-#endif // USE_THREADS
-#endif // NO_LOG
-
-
-
-
-
-/*
- * Helper functions used by other modules
- */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef _WIN32
-#include
-#endif // _WIN32
-#include
-#include
-#include
-#include
-#include "helpers.h"
-#include "output.h"
-#include "endian.h"
-#include "shared_globals.h"
-
-
-/*
- * UCS2 <-> UTF-8 functions
- * All functions use little endian UCS2 since we only need it to communicate with Windows via RPC
- */
-
-// Convert one character from UTF-8 to UCS2
-// Returns 0xffff, if utf-8 evaluates to > 0xfffe (outside basic multilingual pane)
-WCHAR utf8_to_ucs2_char (const unsigned char *input, const unsigned char **end_ptr)
-{
- *end_ptr = input;
- if (input[0] == 0)
- return ~0;
-
- if (input[0] < 0x80) {
- *end_ptr = input + 1;
- return LE16(input[0]);
- }
-
- if ((input[0] & 0xE0) == 0xE0) {
-
- if (input[1] == 0 || input[2] == 0)
- return ~0;
-
- *end_ptr = input + 3;
-
- return
- LE16((input[0] & 0x0F)<<12 |
- (input[1] & 0x3F)<<6 |
- (input[2] & 0x3F));
- }
-
- if ((input[0] & 0xC0) == 0xC0) {
- if (input[1] == 0)
- return ~0;
-
- *end_ptr = input + 2;
-
- return
- LE16((input[0] & 0x1F)<<6 |
- (input[1] & 0x3F));
- }
- return ~0;
-}
-
-// Convert one character from UCS2 to UTF-8
-// Returns length of UTF-8 char (1, 2 or 3) or -1 on error (UTF-16 outside UCS2)
-// char *utf8 must be large enough to hold 3 bytes
-int ucs2_to_utf8_char (const WCHAR ucs2_le, char *utf8)
-{
- const WCHAR ucs2 = LE16(ucs2_le);
-
- if (ucs2 < 0x80) {
- utf8[0] = ucs2;
- utf8[1] = '\0';
- return 1;
- }
-
- if (ucs2 >= 0x80 && ucs2 < 0x800) {
- utf8[0] = (ucs2 >> 6) | 0xC0;
- utf8[1] = (ucs2 & 0x3F) | 0x80;
- utf8[2] = '\0';
- return 2;
- }
-
- if (ucs2 >= 0x800 && ucs2 < 0xFFFF) {
-
- if (ucs2 >= 0xD800 && ucs2 <= 0xDFFF) {
- /* Ill-formed (UTF-16 ouside of BMP) */
- return -1;
- }
-
- utf8[0] = ((ucs2 >> 12) ) | 0xE0;
- utf8[1] = ((ucs2 >> 6 ) & 0x3F) | 0x80;
- utf8[2] = ((ucs2 ) & 0x3F) | 0x80;
- utf8[3] = '\0';
- return 3;
- }
-
- return -1;
-}
-
-
-// Converts UTF8 to UCS2. Returns size in bytes of the converted string or -1 on error
-size_t utf8_to_ucs2(WCHAR* const ucs2_le, const char* const utf8, const size_t maxucs2, const size_t maxutf8)
-{
- const unsigned char* current_utf8 = (unsigned char*)utf8;
- WCHAR* current_ucs2_le = ucs2_le;
-
- for (; *current_utf8; current_ucs2_le++)
- {
- size_t size = (char*)current_utf8 - utf8;
-
- if (size >= maxutf8) return (size_t)-1;
- if (((*current_utf8 & 0xc0) == 0xc0) && (size >= maxutf8 - 1)) return (size_t)-1;
- if (((*current_utf8 & 0xe0) == 0xe0) && (size >= maxutf8 - 2)) return (size_t)-1;
- if (current_ucs2_le - ucs2_le >= (intptr_t)maxucs2 - 1) return (size_t)-1;
-
- *current_ucs2_le = utf8_to_ucs2_char(current_utf8, ¤t_utf8);
- current_ucs2_le[1] = 0;
-
- if (*current_ucs2_le == (WCHAR)-1) return (size_t)-1;
- }
- return current_ucs2_le - ucs2_le;
-}
-
-// Converts UCS2 to UTF-8. Return TRUE or FALSE
-BOOL ucs2_to_utf8(const WCHAR* const ucs2_le, char* utf8, size_t maxucs2, size_t maxutf8)
-{
- char utf8_char[4];
- const WCHAR* current_ucs2 = ucs2_le;
- unsigned int index_utf8 = 0;
-
- for(*utf8 = 0; *current_ucs2; current_ucs2++)
- {
- if (current_ucs2 - ucs2_le > (intptr_t)maxucs2) return FALSE;
- int len = ucs2_to_utf8_char(*current_ucs2, utf8_char);
- if (index_utf8 + len > maxutf8) return FALSE;
- strncat(utf8, utf8_char, len);
- index_utf8+=len;
- }
-
- return TRUE;
-}
-
-/* End of UTF-8 <-> UCS2 conversion */
-
-
-// Checks, whether a string is a valid integer number between min and max. Returns TRUE or FALSE. Puts int value in *value
-BOOL stringToInt(const char *const szValue, const unsigned int min, const unsigned int max, unsigned int *const value)
-{
- char *nextchar;
-
- errno = 0;
- long long result = strtoll(szValue, &nextchar, 10);
-
- if (errno || result < (long long)min || result > (long long)max || *nextchar)
- {
- return FALSE;
- }
-
- *value = (unsigned int)result;
- return TRUE;
-}
-
-
-//Converts a String Guid to a host binary guid in host endianess
-int_fast8_t string2Uuid(const char *const restrict input, GUID *const restrict guid)
-{
- int i;
-
- if (strlen(input) < GUID_STRING_LENGTH) return FALSE;
- if (input[8] != '-' || input[13] != '-' || input[18] != '-' || input[23] != '-') return FALSE;
-
- for (i = 0; i < GUID_STRING_LENGTH; i++)
- {
- if (i == 8 || i == 13 || i == 18 || i == 23) continue;
-
- const char c = toupper((int)input[i]);
-
- if (c < '0' || c > 'F' || (c > '9' && c < 'A')) return FALSE;
- }
-
- char inputCopy[GUID_STRING_LENGTH + 1];
- strncpy(inputCopy, input, GUID_STRING_LENGTH + 1);
- inputCopy[8] = inputCopy[13] = inputCopy[18] = 0;
-
- hex2bin((BYTE*)&guid->Data1, inputCopy, 8);
- hex2bin((BYTE*)&guid->Data2, inputCopy + 9, 4);
- hex2bin((BYTE*)&guid->Data3, inputCopy + 14, 4);
- hex2bin(guid->Data4, input + 19, 16);
-
- guid->Data1 = BE32(guid->Data1);
- guid->Data2 = BE16(guid->Data2);
- guid->Data3 = BE16(guid->Data3);
- return TRUE;
-}
-
-
-// convert GUID to little-endian
-void LEGUID(GUID *const restrict out, const GUID* const restrict in)
-{
- #if __BYTE_ORDER != __LITTLE_ENDIAN
- out->Data1 = LE32(in->Data1);
- out->Data2 = LE16(in->Data2);
- out->Data3 = LE16(in->Data3);
- memcpy(out->Data4, in->Data4, sizeof(out->Data4));
- #else
- memcpy(out, in, sizeof(GUID));
- #endif
-}
-
-
-//Checks a command line argument if it is numeric and between min and max. Returns the numeric value or exits on error
-__pure unsigned int getOptionArgumentInt(const char o, const unsigned int min, const unsigned int max)
-{
- unsigned int result;
-
- if (!stringToInt(optarg, min, max, &result))
- {
- printerrorf("Fatal: Option \"-%c\" must be numeric between %u and %u.\n", o, min, max);
- exit(!0);
- }
-
- return result;
-}
-
-
-// Resets getopt() to start parsing from the beginning
-void optReset(void)
-{
- #if __minix__ || defined(__BSD__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
- optind = 1;
- optreset = 1; // Makes newer BSD getopt happy
- #elif defined(__UCLIBC__) // uClibc headers also define __GLIBC__ so be careful here
- optind = 0; // uClibc seeks compatibility with GLIBC
- #elif defined(__GLIBC__)
- optind = 0; // Makes GLIBC getopt happy
- #else // Standard for most systems
- optind = 1;
- #endif
-}
-
-
-#if defined(_WIN32) || defined(USE_MSRPC)
-
-// Returns a static message buffer containing text for a given Win32 error. Not thread safe (same as strerror)
-char* win_strerror(const int message)
-{
- #define STRERROR_BUFFER_SIZE 256
- static char buffer[STRERROR_BUFFER_SIZE];
-
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, message, 0, buffer, STRERROR_BUFFER_SIZE, NULL);
- return buffer;
-}
-
-#endif // defined(_WIN32) || defined(USE_MSRPC)
-
-
-/*
- * parses an address in the form host:[port] in addr
- * returns host and port in seperate strings
- */
-void parseAddress(char *const addr, char** szHost, char** szPort)
-{
- *szHost = addr;
-
-# ifndef NO_SOCKETS
- *szPort = (char*)defaultport;
-# else // NO_SOCKETS
- *szPort = "1688";
-# endif // NO_SOCKETS
-
- char *lastcolon = strrchr(addr, ':');
- char *firstcolon = strchr(addr, ':');
- char *closingbracket = strrchr(addr, ']');
-
- if (*addr == '[' && closingbracket) //Address in brackets
- {
- *closingbracket = 0;
- (*szHost)++;
-
- if (closingbracket[1] == ':')
- *szPort = closingbracket + 2;
- }
- else if (firstcolon && firstcolon == lastcolon) //IPv4 address or hostname with port
- {
- *firstcolon = 0;
- *szPort = firstcolon + 1;
- }
-}
-
-
-// Initialize random generator (needs to be done in each thread)
-void randomNumberInit()
-{
- struct timeval tv;
- gettimeofday(&tv, NULL);
- srand((unsigned int)(tv.tv_sec ^ tv.tv_usec));
-}
-
-
-// We always exit immediately if any OOM condition occurs
-__noreturn void OutOfMemory(void)
-{
- errorout("Fatal: Out of memory");
- exit(!0);
-}
-
-
-void* vlmcsd_malloc(size_t len)
-{
- void* buf = malloc(len);
- if (!buf) OutOfMemory();
- return buf;
-}
-
-
-/*
- * Converts hex digits to bytes in big-endian order.
- * Ignores any non-hex characters
- */
-void hex2bin(BYTE *const bin, const char *hex, const size_t maxbin)
-{
- static const char *const hexdigits = "0123456789ABCDEF";
- char* nextchar;
- size_t i;
-
- for (i = 0; (i < 16) && utf8_to_ucs2_char((const unsigned char*)hex, (const unsigned char**)&nextchar) != (WCHAR)-1; hex = nextchar)
- {
- const char* pos = strchr(hexdigits, toupper((int)*hex));
- if (!pos) continue;
-
- if (!(i & 1)) bin[i >> 1] = 0;
- bin[i >> 1] |= (char)(pos - hexdigits);
- if (!(i & 1)) bin[i >> 1] <<= 4;
- i++;
- if (i >> 1 > maxbin) break;
- }
-}
-
-
-__pure BOOL getArgumentBool(int_fast8_t *result, const char *const argument)
-{
- if (
- !strncasecmp(argument, "true", 4) ||
- !strncasecmp(argument, "on", 2) ||
- !strncasecmp(argument, "yes", 3) ||
- !strncasecmp(argument, "1", 1)
- )
- {
- *result = TRUE;
- return TRUE;
- }
- else if (
- !strncasecmp(argument, "false", 5) ||
- !strncasecmp(argument, "off", 3) ||
- !strncasecmp(argument, "no", 2) ||
- !strncasecmp(argument, "0", 1)
- )
- {
- *result = FALSE;
- return TRUE;
- }
-
- return FALSE;
-}
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef USE_MSRPC
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include
-#ifndef _WIN32
-#include
-#include
-#include
-#include
-#include
-#endif // WIN32
-
-#include "network.h"
-#include "endian.h"
-#include "output.h"
-#include "helpers.h"
-#include "shared_globals.h"
-#include "rpc.h"
-
-
-#ifndef _WIN32
-typedef ssize_t (*sendrecv_t)(int, void*, size_t, int);
-#else
-typedef int (WINAPI *sendrecv_t)(SOCKET, void*, int, int);
-#endif
-
-
-// Send or receive a fixed number of bytes regardless if received in one or more chunks
-int_fast8_t sendrecv(SOCKET sock, BYTE *data, int len, int_fast8_t do_send)
-{
- int n;
- sendrecv_t f = do_send
- ? (sendrecv_t) send
- : (sendrecv_t) recv;
-
- do
- {
- n = f(sock, data, len, 0);
- }
- while (
- ( n < 0 && socket_errno == VLMCSD_EINTR ) || ( n > 0 && ( data += n, (len -= n) > 0 ) ));
-
- return ! len;
-}
-
-
-static int_fast8_t ip2str(char *restrict result, const size_t resultLength, const struct sockaddr *const restrict socketAddress, const socklen_t socketLength)
-{
- static const char *const fIPv4 = "%s:%s";
- static const char *const fIPv6 = "[%s]:%s";
- char ipAddress[64], portNumber[8];
-
- if (getnameinfo
- (
- socketAddress,
- socketLength,
- ipAddress,
- sizeof(ipAddress),
- portNumber,
- sizeof(portNumber),
- NI_NUMERICHOST | NI_NUMERICSERV
- ))
- {
- return FALSE;
- }
-
- if ((unsigned int)snprintf(result, resultLength, socketAddress->sa_family == AF_INET6 ? fIPv6 : fIPv4, ipAddress, portNumber) > resultLength) return FALSE;
- return TRUE;
-}
-
-
-static int_fast8_t getSocketList(struct addrinfo **saList, const char *const addr, const int flags, const int AddressFamily)
-{
- int status;
- char *szHost, *szPort;
- size_t len = strlen(addr) + 1;
-
- // Don't alloca too much
- if (len > 264) return FALSE;
-
- char *addrcopy = (char*)alloca(len);
- memcpy(addrcopy, addr, len);
-
- parseAddress(addrcopy, &szHost, &szPort);
-
- struct addrinfo hints;
-
- memset(&hints, 0, sizeof(struct addrinfo));
-
- hints.ai_family = AddressFamily;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP;
- hints.ai_flags = flags;
-
- if ((status = getaddrinfo(szHost, szPort, &hints, saList)))
- {
- printerrorf("Warning: %s: %s\n", addr, gai_strerror(status));
- return FALSE;
- }
-
- return TRUE;
-}
-
-
-static int_fast8_t setBlockingEnabled(SOCKET fd, int_fast8_t blocking)
-{
- if (fd == INVALID_SOCKET) return FALSE;
-
- #ifdef _WIN32
-
- unsigned long mode = blocking ? 0 : 1;
- return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? TRUE : FALSE;
-
- #else // POSIX
-
- int flags = fcntl(fd, F_GETFL, 0);
-
- if (flags < 0) return FALSE;
-
- flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
- return (fcntl(fd, F_SETFL, flags) == 0) ? TRUE : FALSE;
-
- #endif // POSIX
-}
-
-
-int_fast8_t isDisconnected(const SOCKET s)
-{
- char buffer[1];
-
- if (!setBlockingEnabled(s, FALSE)) return TRUE;
-
- int n = recv(s, buffer, 1, MSG_PEEK);
-
- if (!setBlockingEnabled(s, TRUE)) return TRUE;
- if (n == 0) return TRUE;
-
- return FALSE;
-}
-
-
-// Connect to TCP address addr (e.g. "kms.example.com:1688") and return an
-// open socket for the connection if successful or INVALID_SOCKET otherwise
-SOCKET connectToAddress(const char *const addr, const int AddressFamily, int_fast8_t showHostName)
-{
- struct addrinfo *saList, *sa;
- SOCKET s = INVALID_SOCKET;
- char szAddr[128];
-
- if (!getSocketList(&saList, addr, 0, AddressFamily)) return INVALID_SOCKET;
-
- for (sa = saList; sa; sa = sa->ai_next)
- {
- // struct sockaddr_in* addr4 = (struct sockaddr_in*)sa->ai_addr;
- // struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sa->ai_addr;
-
- if (ip2str(szAddr, sizeof(szAddr), sa->ai_addr, sa->ai_addrlen))
- {
- if (showHostName)
- printf("Connecting to %s (%s) ... ", addr, szAddr);
- else
- printf("Connecting to %s ... ", szAddr);
-
- fflush(stdout);
- }
-
- s = socket(sa->ai_family, SOCK_STREAM, IPPROTO_TCP);
-
-# if !defined(NO_TIMEOUT) && !__minix__
-# ifndef _WIN32 // Standard Posix timeout structure
-
- struct timeval to;
- to.tv_sec = 10;
- to.tv_usec = 0;
-
-# else // Windows requires a DWORD with milliseconds
-
- DWORD to = 10000;
-
-# endif // _WIN32
-
- setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to));
- setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
-# endif // !defined(NO_TIMEOUT) && !__minix__
-
- if (!connect(s, sa->ai_addr, sa->ai_addrlen))
- {
- printf("successful\n");
- break;
- }
-
- errorout("%s\n", socket_errno == VLMCSD_EINPROGRESS ? "Timed out" : vlmcsd_strerror(socket_errno));
-
- socketclose(s);
- s = INVALID_SOCKET;
- }
-
- freeaddrinfo(saList);
- return s;
-}
-
-
-#ifndef NO_SOCKETS
-
-// Create a Listening socket for addrinfo sa and return socket s
-// szHost and szPort are for logging only
-static int listenOnAddress(const struct addrinfo *const ai, SOCKET *s)
-{
- int error;
- char ipstr[64];
-
- ip2str(ipstr, sizeof(ipstr), ai->ai_addr, ai->ai_addrlen);
-
- //*s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
- *s = socket(ai->ai_family, SOCK_STREAM, IPPROTO_TCP);
-
- if (*s == INVALID_SOCKET)
- {
- error = socket_errno;
- printerrorf("Warning: %s error. %s\n", ai->ai_family == AF_INET6 ? cIPv6 : cIPv4, vlmcsd_strerror(error));
- return error;
- }
-
-# if !defined(_WIN32) && !defined(NO_SIGHUP)
-
- int flags = fcntl(*s, F_GETFD, 0);
-
- if (flags != -1)
- {
- flags |= FD_CLOEXEC;
- fcntl(*s, F_SETFD, flags);
- }
-# ifdef _PEDANTIC
- else
- {
- printerrorf("Warning: Could not set FD_CLOEXEC flag on %s: %s\n", ipstr, vlmcsd_strerror(errno));
- }
-# endif // _PEDANTIC
-
-# endif // !defined(_WIN32) && !defined(NO_SIGHUP)
-
- BOOL socketOption = TRUE;
-
- // fix for lame tomato toolchain
-# ifndef IPV6_V6ONLY
-# ifdef __linux__
-# define IPV6_V6ONLY (26)
-# endif // __linux__
-# endif // IPV6_V6ONLY
-
-# ifdef IPV6_V6ONLY
- if (ai->ai_family == AF_INET6) setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_t)&socketOption, sizeof(socketOption));
-# endif
-
-# ifndef _WIN32
- setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (sockopt_t)&socketOption, sizeof(socketOption));
-# endif
-
- if (bind(*s, ai->ai_addr, ai->ai_addrlen) || listen(*s, SOMAXCONN))
- {
- error = socket_errno;
- printerrorf("Warning: %s: %s\n", ipstr, vlmcsd_strerror(error));
- socketclose(*s);
- return error;
- }
-
-# ifndef NO_LOG
- logger("Listening on %s\n", ipstr);
-# endif
-
- return 0;
-}
-
-
-// Adds a listening socket for an address string,
-// e.g. 127.0.0.1:1688 or [2001:db8:dead:beef::1]:1688
-BOOL addListeningSocket(const char *const addr)
-{
- struct addrinfo *aiList, *ai;
- int result = FALSE;
- SOCKET *s = SocketList + numsockets;
-
- if (getSocketList(&aiList, addr, AI_PASSIVE | AI_NUMERICHOST, AF_UNSPEC))
- {
- for (ai = aiList; ai; ai = ai->ai_next)
- {
- // struct sockaddr_in* addr4 = (struct sockaddr_in*)sa->ai_addr;
- // struct sockaddr_in6* addr6 = (struct sockaddr_in6*)sa->ai_addr;
-
- if (numsockets >= FD_SETSIZE)
- {
- #ifdef _PEDANTIC // Do not report this error in normal builds to keep file size low
- printerrorf("Warning: Cannot listen on %s. Your OS only supports %u listening sockets in an FD_SET.\n", addr, FD_SETSIZE);
- #endif
- break;
- }
-
- if (!listenOnAddress(ai, s))
- {
- numsockets++;
- result = TRUE;
- }
- }
-
- freeaddrinfo(aiList);
- }
- return result;
-}
-
-
-// Just create some dummy sockets to see if we have a specific protocol (IPv4 or IPv6)
-__pure int_fast8_t checkProtocolStack(const int addressfamily)
-{
- SOCKET s; // = INVALID_SOCKET;
-
- s = socket(addressfamily, SOCK_STREAM, 0);
- int_fast8_t success = (s != INVALID_SOCKET);
-
- socketclose(s);
- return success;
-}
-
-
-// Build an fd_set of all listening socket then use select to wait for an incoming connection
-static SOCKET network_accept_any()
-{
- fd_set ListeningSocketsList;
- SOCKET maxSocket, sock;
- int i;
- int status;
-
- FD_ZERO(&ListeningSocketsList);
- maxSocket = 0;
-
- for (i = 0; i < numsockets; i++)
- {
- FD_SET(SocketList[i], &ListeningSocketsList);
- if (SocketList[i] > maxSocket) maxSocket = SocketList[i];
- }
-
- status = select(maxSocket + 1, &ListeningSocketsList, NULL, NULL, NULL);
-
- if (status < 0) return INVALID_SOCKET;
-
- sock = INVALID_SOCKET;
-
- for (i = 0; i < numsockets; i++)
- {
- if (FD_ISSET(SocketList[i], &ListeningSocketsList))
- {
- sock = SocketList[i];
- break;
- }
- }
-
- if (sock == INVALID_SOCKET)
- return INVALID_SOCKET;
- else
- return accept(sock, NULL, NULL);
-}
-
-
-void closeAllListeningSockets()
-{
- int i;
-
- for (i = 0; i < numsockets; i++)
- {
- shutdown(SocketList[i], VLMCSD_SHUT_RDWR);
- socketclose(SocketList[i]);
- }
-}
-#endif // NO_SOCKETS
-
-
-static void serveClient(const SOCKET s_client, const DWORD RpcAssocGroup)
-{
-# if !defined(NO_TIMEOUT) && !__minix__
-
-# ifndef _WIN32 // Standard Posix timeout structure
-
- struct timeval to;
- to.tv_sec = ServerTimeout;
- to.tv_usec = 0;
-
- #else // Windows requires a DWORD with milliseconds
-
- DWORD to = ServerTimeout * 1000;
-
-# endif // _WIN32
-
-# if !defined(NO_LOG) && defined(_PEDANTIC)
-
- int result =
- setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to)) ||
- setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
-
- if (result) logger("Warning: Set timeout failed: %s\n", vlmcsd_strerror(socket_errno));
-
-# else // !(!defined(NO_LOG) && defined(_PEDANTIC))
-
- setsockopt(s_client, SOL_SOCKET, SO_RCVTIMEO, (sockopt_t)&to, sizeof(to));
- setsockopt(s_client, SOL_SOCKET, SO_SNDTIMEO, (sockopt_t)&to, sizeof(to));
-
-# endif // !(!defined(NO_LOG) && defined(_PEDANTIC))
-
-# endif // !defined(NO_TIMEOUT) && !__minix__
-
- char ipstr[64];
- socklen_t len;
- struct sockaddr_storage addr;
-
- len = sizeof addr;
-
- if (getpeername(s_client, (struct sockaddr*)&addr, &len) ||
- !ip2str(ipstr, sizeof(ipstr), (struct sockaddr*)&addr, len))
- {
-# if !defined(NO_LOG) && defined(_PEDANTIC)
- logger("Fatal: Cannot determine client's IP address: %s\n", vlmcsd_strerror(errno));
-# endif // !defined(NO_LOG) && defined(_PEDANTIC)
- socketclose(s_client);
- return;
- }
-
-
-# ifndef NO_LOG
- const char *const connection_type = addr.ss_family == AF_INET6 ? cIPv6 : cIPv4;
- static const char *const cAccepted = "accepted";
- static const char *const cClosed = "closed";
- static const char *const fIP = "%s connection %s: %s.\n";
-
- logger(fIP, connection_type, cAccepted, ipstr);
- #endif // NO_LOG
-
- rpcServer(s_client, RpcAssocGroup, ipstr);
-
-# ifndef NO_LOG
- logger(fIP, connection_type, cClosed, ipstr);
-# endif // NO_LOG
-
- socketclose(s_client);
-}
-
-
-#ifndef NO_SOCKETS
-static void post_sem(void)
-{
- #if !defined(NO_LIMIT) && !__minix__
- if (!InetdMode && MaxTasks != SEM_VALUE_MAX)
- {
- semaphore_post(Semaphore);
- }
- #endif // !defined(NO_LIMIT) && !__minix__
-}
-
-
-static void wait_sem(void)
-{
- #if !defined(NO_LIMIT) && !__minix__
- if (!InetdMode && MaxTasks != SEM_VALUE_MAX)
- {
- semaphore_wait(Semaphore);
- }
- #endif // !defined(NO_LIMIT) && !__minix__
-}
-#endif // NO_SOCKETS
-
-#if defined(USE_THREADS) && !defined(NO_SOCKETS)
-
-#if defined(_WIN32) || defined(__CYGWIN__) // Win32 Threads
-static DWORD WINAPI serveClientThreadProc(PCLDATA clData)
-#else // Posix threads
-static void *serveClientThreadProc (PCLDATA clData)
-#endif // Thread proc is identical in WIN32 and Posix threads
-{
- serveClient(clData->socket, clData->RpcAssocGroup);
- free(clData);
- post_sem();
-
- return 0;
-}
-
-#endif // USE_THREADS
-
-
-#ifndef NO_SOCKETS
-
-#if defined(USE_THREADS) && (defined(_WIN32) || defined(__CYGWIN__)) // Windows Threads
-static int serveClientAsyncWinThreads(const PCLDATA thr_CLData)
-{
- wait_sem();
-
- HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)serveClientThreadProc, thr_CLData, 0, NULL);
-
- if (h)
- CloseHandle(h);
- else
- {
- socketclose(thr_CLData->socket);
- free(thr_CLData);
- post_sem();
- return GetLastError();
- }
-
- return NO_ERROR;
-}
-#endif // defined(USE_THREADS) && defined(_WIN32) // Windows Threads
-
-
-#if defined(USE_THREADS) && !defined(_WIN32) && !defined(__CYGWIN__) // Posix Threads
-static int ServeClientAsyncPosixThreads(const PCLDATA thr_CLData)
-{
- pthread_t p_thr;
- pthread_attr_t attr;
-
- wait_sem();
-
- // Must set detached state to avoid memory leak
- if (pthread_attr_init(&attr) ||
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) ||
- pthread_create(&p_thr, &attr, (void * (*)(void *))serveClientThreadProc, thr_CLData))
- {
- socketclose(thr_CLData->socket);
- free(thr_CLData);
- post_sem();
- return !0;
- }
-
- return 0;
-}
-#endif // defined(USE_THREADS) && !defined(_WIN32) // Posix Threads
-
-#ifndef USE_THREADS // fork() implementation
-static void ChildSignalHandler(const int signal)
-{
- if (signal == SIGHUP) return;
-
- post_sem();
-
- #ifndef NO_LOG
- logger("Warning: Child killed/crashed by %s\n", strsignal(signal));
- #endif // NO_LOG
-
- exit(!0);
-}
-
-static int ServeClientAsyncFork(const SOCKET s_client, const DWORD RpcAssocGroup)
-{
- int pid;
- wait_sem();
-
- if ((pid = fork()) < 0)
- {
- return errno;
- }
- else if ( pid )
- {
- // Parent process
- socketclose(s_client);
- return 0;
- }
- else
- {
- // Child process
-
- // Setup a Child Handler for most common termination signals
- struct sigaction sa;
-
- sa.sa_flags = 0;
- sa.sa_handler = ChildSignalHandler;
-
- static int signallist[] = { SIGHUP, SIGINT, SIGTERM, SIGSEGV, SIGILL, SIGFPE, SIGBUS };
-
- if (!sigemptyset(&sa.sa_mask))
- {
- uint_fast8_t i;
-
- for (i = 0; i < _countof(signallist); i++)
- {
- sigaction(signallist[i], &sa, NULL);
- }
- }
-
- serveClient(s_client, RpcAssocGroup);
- post_sem();
- exit(0);
- }
-}
-#endif
-
-
-int serveClientAsync(const SOCKET s_client, const DWORD RpcAssocGroup)
-{
- #ifndef USE_THREADS // fork() implementation
-
- return ServeClientAsyncFork(s_client, RpcAssocGroup);
-
- #else // threads implementation
-
- PCLDATA thr_CLData = (PCLDATA)vlmcsd_malloc(sizeof(CLDATA));
- thr_CLData->socket = s_client;
- thr_CLData->RpcAssocGroup = RpcAssocGroup;
-
- #if defined(_WIN32) || defined (__CYGWIN__) // Windows threads
-
- return serveClientAsyncWinThreads(thr_CLData);
-
- #else // Posix Threads
-
- return ServeClientAsyncPosixThreads(thr_CLData);
-
- #endif // Posix Threads
-
- #endif // USE_THREADS
-}
-
-#endif // NO_SOCKETS
-
-
-int runServer()
-{
- DWORD RpcAssocGroup = rand32();
-
- // If compiled for inetd-only mode just serve the stdin socket
- #ifdef NO_SOCKETS
- serveClient(STDIN_FILENO, RpcAssocGroup);
- return 0;
- #else
- // In inetd mode just handle the stdin socket
- if (InetdMode)
- {
- serveClient(STDIN_FILENO, RpcAssocGroup);
- return 0;
- }
-
- // Standalone mode
- for (;;)
- {
- int error;
- SOCKET s_client;
-
- if ( (s_client = network_accept_any()) == INVALID_SOCKET )
- {
- error = socket_errno;
-
- if (error == VLMCSD_EINTR || error == VLMCSD_ECONNABORTED) continue;
-
- #ifdef _NTSERVICE
- if (ServiceShutdown) return 0;
- #endif
-
- #ifndef NO_LOG
- logger("Fatal: %s\n",vlmcsd_strerror(error));
- #endif
-
- return error;
- }
-
- RpcAssocGroup++;
- serveClientAsync(s_client, RpcAssocGroup);
- }
- #endif // NO_SOCKETS
-
- return 0;
-}
-
-#endif // USE_MSRPC
-#ifndef _DEFAULT_SOURCE
-#define _DEFAULT_SOURCE
-#endif // _DEFAULT_SOURCE
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef USE_MSRPC
-
-#include
-#include
-#include
-#include
-#include
-#include
-#if !defined(_WIN32)
-#include
-#include
-#endif
-#include "rpc.h"
-#include "output.h"
-#include "crypto.h"
-#include "endian.h"
-#include "helpers.h"
-#include "network.h"
-#include "shared_globals.h"
-
-/* Forwards */
-
-static int checkRpcHeader(const RPC_HEADER *const Header, const BYTE desiredPacketType, const PRINTFUNC p);
-
-
-/* Data definitions */
-
-// All GUIDs are defined as BYTE[16] here. No big-endian/little-endian byteswapping required.
-static const BYTE TransferSyntaxNDR32[] = {
- 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C, 0xC9, 0x11, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60
-};
-
-static const BYTE InterfaceUuid[] = {
- 0x75, 0x21, 0xc8, 0x51, 0x4e, 0x84, 0x50, 0x47, 0xB0, 0xD8, 0xEC, 0x25, 0x55, 0x55, 0xBC, 0x06
-};
-
-static const BYTE TransferSyntaxNDR64[] = {
- 0x33, 0x05, 0x71, 0x71, 0xba, 0xbe, 0x37, 0x49, 0x83, 0x19, 0xb5, 0xdb, 0xef, 0x9c, 0xcc, 0x36
-};
-
-static const BYTE BindTimeFeatureNegotiation[] = {
- 0x2c, 0x1c, 0xb7, 0x6c, 0x12, 0x98, 0x40, 0x45, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-
-//
-// Dispatch RPC payload to kms.c
-//
-typedef int (*CreateResponse_t)(const void *const, void *const, const char* const);
-
-static const struct {
- unsigned int RequestSize;
- CreateResponse_t CreateResponse;
-} _Versions[] = {
- { sizeof(REQUEST_V4), (CreateResponse_t) CreateResponseV4 },
- { sizeof(REQUEST_V6), (CreateResponse_t) CreateResponseV6 },
- { sizeof(REQUEST_V6), (CreateResponse_t) CreateResponseV6 }
-};
-
-RPC_FLAGS RpcFlags;
-static int_fast8_t firstPacketSent;
-
-//
-// RPC request (server)
-//
-#if defined(_PEDANTIC) && !defined(NO_LOG)
-static void CheckRpcRequest(const RPC_REQUEST64 *const Request, const unsigned int len, WORD* NdrCtx, WORD* Ndr64Ctx, WORD Ctx)
-{
- uint_fast8_t kmsMajorVersion;
- uint32_t requestSize = Ctx != *Ndr64Ctx ? sizeof(RPC_REQUEST) : sizeof(RPC_REQUEST64);
-
- if (len < requestSize)
- {
- logger("Fatal: RPC request (including header) must be at least %i bytes but is only %i bytes.\n",
- (int)(sizeof(RPC_HEADER) + requestSize),
- (int)(len + sizeof(RPC_HEADER))
- );
-
- return;
- }
-
- if (len < requestSize + sizeof(DWORD))
- {
- logger("Fatal: KMS Request too small to contain version info (less than 4 bytes).\n");
- return;
- }
-
- if (Ctx != *Ndr64Ctx)
- kmsMajorVersion = LE16(((WORD*)Request->Ndr.Data)[1]);
- else
- kmsMajorVersion = LE16(((WORD*)Request->Ndr64.Data)[1]);
-
- if (kmsMajorVersion > 6)
- {
- logger("Fatal: KMSv%u is not supported.\n", (unsigned int)kmsMajorVersion);
- }
- else
- {
- if (len >_Versions[kmsMajorVersion].RequestSize + requestSize)
- logger("Warning: %u excess bytes in RPC request.\n",
- len - _Versions[kmsMajorVersion].RequestSize
- );
- }
-
- if (Ctx != *Ndr64Ctx && Ctx != *NdrCtx)
- logger("Warning: Context id should be %u (NDR32) or %u (NDR64) but is %u.\n",
- (unsigned int)*NdrCtx,
- (unsigned int)*Ndr64Ctx,
- Ctx
- );
-
- if (Request->Opnum)
- logger("Warning: OpNum should be 0 but is %u.\n",
- (unsigned int)LE16(Request->Opnum)
- );
-
- if (LE32(Request->AllocHint) != len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr))
- logger("Warning: Allocation hint should be %u but is %u.\n",
- len + sizeof(Request->Ndr),
- LE32(Request->AllocHint)
- );
-
- if (Ctx != *Ndr64Ctx)
- {
- if (LE32(Request->Ndr.DataLength) != len - sizeof(RPC_REQUEST))
- logger("Warning: NDR32 data length field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST),
- LE32(Request->Ndr.DataLength)
- );
-
- if (LE32(Request->Ndr.DataSizeIs) != len - sizeof(RPC_REQUEST))
- logger("Warning: NDR32 data size field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST),
- LE32(Request->Ndr.DataSizeIs)
- );
- }
- else
- {
- if (LE64(Request->Ndr64.DataLength) != len - sizeof(RPC_REQUEST64))
- logger("Warning: NDR32 data length field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST) + sizeof(Request->Ndr),
- LE64(Request->Ndr64.DataLength)
- );
-
- if (LE64(Request->Ndr64.DataSizeIs) != len - sizeof(RPC_REQUEST64))
- logger("Warning: NDR32 data size field should be %u but is %u.\n",
- len - sizeof(RPC_REQUEST64),
- LE64(Request->Ndr64.DataSizeIs)
- );
- }
-}
-#endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
-/*
- * check RPC request for (somewhat) correct size
- * allow any size that does not cause CreateResponse to fail badly
- */
-static unsigned int checkRpcRequestSize(const RPC_REQUEST64 *const Request, const unsigned int requestSize, WORD* NdrCtx, WORD* Ndr64Ctx)
-{
- WORD Ctx = LE16(Request->ContextId);
-
-# if defined(_PEDANTIC) && !defined(NO_LOG)
- CheckRpcRequest(Request, requestSize, NdrCtx, Ndr64Ctx, Ctx);
-# endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
- // Anything that is smaller than a v4 request is illegal
- if (requestSize < sizeof(REQUEST_V4) + (Ctx != *Ndr64Ctx ? sizeof(RPC_REQUEST) : sizeof(RPC_REQUEST64))) return 0;
-
- // Get KMS major version
- uint_fast16_t _v;
-
- if (Ctx != *Ndr64Ctx)
- _v = LE16(((WORD*)Request->Ndr.Data)[1]) - 4;
- else
- _v = LE16(((WORD*)Request->Ndr64.Data)[1]) - 4;
-
- // Only KMS v4, v5 and v6 are supported
- if (_v >= vlmcsd_countof(_Versions))
- {
-# ifndef NO_LOG
- logger("Fatal: KMSv%i unsupported\n", _v + 4);
-# endif // NO_LOG
- return 0;
- }
-
- // Could check for equality but allow bigger requests to support buggy RPC clients (e.g. wine)
- // Buffer overrun is check by caller.
- return (requestSize >= _Versions[_v].RequestSize);
-}
-
-
-/*
- * Handles the actual KMS request from the client.
- * Calls KMS functions (CreateResponseV4 or CreateResponseV6) in kms.c
- * Returns size of the KMS response packet or 0 on failure.
- *
- * The RPC packet size (excluding header) is actually in Response->AllocHint
- */
-static int rpcRequest(const RPC_REQUEST64 *const Request, RPC_RESPONSE64 *const Response, const DWORD RpcAssocGroup_unused, const SOCKET sock_unused, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr)
-{
- uint_fast16_t _v;
- int ResponseSize;
- WORD Ctx = LE16(Request->ContextId);
- BYTE* requestData;
- BYTE* responseData;
- BYTE* pRpcReturnCode;
- int len;
-
- if (Ctx != *Ndr64Ctx)
- {
- requestData = (BYTE*)&Request->Ndr.Data;
- responseData = (BYTE*)&Response->Ndr.Data;
- }
- else
- {
- requestData = (BYTE*)&Request->Ndr64.Data;
- responseData = (BYTE*)&Response->Ndr64.Data;
- }
-
- _v = LE16(((WORD*)requestData)[1]) - 4;
-
- if (!(ResponseSize = _Versions[_v].CreateResponse(requestData, responseData, ipstr)))
- {
- return 0;
- }
-
- if (Ctx != *Ndr64Ctx)
- {
- Response->Ndr.DataSizeMax = LE32(0x00020000);
- Response->Ndr.DataLength = Response->Ndr.DataSizeIs = LE32(ResponseSize);
- len = ResponseSize + sizeof(Response->Ndr);
- }
- else
- {
- Response->Ndr64.DataSizeMax = LE64(0x00020000ULL);
- Response->Ndr64.DataLength = Response->Ndr64.DataSizeIs = LE64((uint64_t)ResponseSize);
- len = ResponseSize + sizeof(Response->Ndr64);
- }
-
- pRpcReturnCode = ((BYTE*)&Response->Ndr) + len;
- UA32(pRpcReturnCode) = 0; //LE32 not needed for 0
- len += sizeof(DWORD);
-
- // Pad zeros to 32-bit align (seems not neccassary but Windows RPC does it this way)
- int pad = ((~len & 3) + 1) & 3;
- memset(pRpcReturnCode + sizeof(DWORD), 0, pad);
- len += pad;
-
- Response->AllocHint = LE32(len);
- Response->ContextId = Request->ContextId;
-
- *((WORD*)&Response->CancelCount) = 0; // CancelCount + Pad1
-
- return len + 8;
-}
-
-
-#if defined(_PEDANTIC) && !defined(NO_LOG)
-static void CheckRpcBindRequest(const RPC_BIND_REQUEST *const Request, const unsigned int len)
-{
- uint_fast8_t i, HasTransferSyntaxNDR32 = FALSE;
- char guidBuffer1[GUID_STRING_LENGTH + 1], guidBuffer2[GUID_STRING_LENGTH + 1];
-
- uint32_t CapCtxItems = (len - sizeof(*Request) + sizeof(Request->CtxItems)) / sizeof(Request->CtxItems);
- DWORD NumCtxItems = LE32(Request->NumCtxItems);
-
- if (NumCtxItems < CapCtxItems) // Can't be too small because already handled by RpcBindSize
- logger("Warning: Excess bytes in RPC bind request.\n");
-
- for (i = 0; i < NumCtxItems; i++)
- {
- if (!IsEqualGUID(&Request->CtxItems[i].InterfaceUUID, InterfaceUuid))
- {
- uuid2StringLE((GUID*)&Request->CtxItems[i].InterfaceUUID, guidBuffer1);
- uuid2StringLE((GUID*)InterfaceUuid, guidBuffer2);
- logger("Warning: Interface UUID is %s but should be %s in Ctx item %u.\n", guidBuffer1, guidBuffer2, (unsigned int)i);
- }
-
- if (Request->CtxItems[i].NumTransItems != LE16(1))
- logger("Fatal: %u NDR32 transfer items detected in Ctx item %u, but only one is supported.\n",
- (unsigned int)LE16(Request->CtxItems[i].NumTransItems), (unsigned int)i
- );
-
- if (Request->CtxItems[i].InterfaceVerMajor != LE16(1) || Request->CtxItems[i].InterfaceVerMinor != 0)
- logger("Warning: NDR32 Interface version is %u.%u but should be 1.0.\n",
- (unsigned int)LE16(Request->CtxItems[i].InterfaceVerMajor),
- (unsigned int)LE16(Request->CtxItems[i].InterfaceVerMinor)
- );
-
- if (Request->CtxItems[i].ContextId != LE16((WORD)i))
- logger("Warning: context id of Ctx item %u is %u.\n", (unsigned int)i, (unsigned int)Request->CtxItems[i].ContextId);
-
- if ( IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
- {
- HasTransferSyntaxNDR32 = TRUE;
-
- if (Request->CtxItems[i].SyntaxVersion != LE32(2))
- logger("NDR32 transfer syntax version is %u but should be 2.\n", LE32(Request->CtxItems[i].SyntaxVersion));
- }
- else if ( IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
- {
- if (Request->CtxItems[i].SyntaxVersion != LE32(1))
- logger("NDR64 transfer syntax version is %u but should be 1.\n", LE32(Request->CtxItems[i].SyntaxVersion));
- }
- else if (!memcmp(BindTimeFeatureNegotiation, (BYTE*)(&Request->CtxItems[i].TransferSyntax), 8))
- {
- if (Request->CtxItems[i].SyntaxVersion != LE32(1))
- logger("BTFN syntax version is %u but should be 1.\n", LE32(Request->CtxItems[i].SyntaxVersion));
- }
- }
-
- if (!HasTransferSyntaxNDR32)
- logger("Warning: RPC bind request has no NDR32 CtxItem.\n");
-}
-#endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
-
-/*
- * Check, if we receive enough bytes to return a valid RPC bind response
- */
-static unsigned int checkRpcBindSize(const RPC_BIND_REQUEST *const Request, const unsigned int RequestSize, WORD* NdrCtx, WORD* Ndr64Ctx)
-{
- if ( RequestSize < sizeof(RPC_BIND_REQUEST) ) return FALSE;
-
- unsigned int _NumCtxItems = LE32(Request->NumCtxItems);
-
- if ( RequestSize < sizeof(RPC_BIND_REQUEST) - sizeof(Request->CtxItems[0]) + _NumCtxItems * sizeof(Request->CtxItems[0]) ) return FALSE;
-
- #if defined(_PEDANTIC) && !defined(NO_LOG)
- CheckRpcBindRequest(Request, RequestSize);
- #endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
- return TRUE;
-}
-
-
-/*
- * Accepts a bind or alter context request from the client and composes the bind response.
- * Needs the socket because the tcp port number is part of the response.
- * len is not used here.
- *
- * Returns TRUE on success.
- */
-static int rpcBind(const RPC_BIND_REQUEST *const Request, RPC_BIND_RESPONSE* Response, const DWORD RpcAssocGroup, const SOCKET sock, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr_unused)
-{
- unsigned int i, _st = FALSE;
- DWORD numCtxItems = LE32(Request->NumCtxItems);
- int_fast8_t IsNDR64possible = FALSE;
- uint_fast8_t portNumberSize;
-
- socklen_t socklen;
- struct sockaddr_storage addr;
-
- // M$ RPC does not do this. Pad bytes contain apparently random data
- // memset(Response->SecondaryAddress, 0, sizeof(Response->SecondaryAddress));
-
- socklen = sizeof addr;
-
- if (
- packetType == RPC_PT_ALTERCONTEXT_REQ ||
- getsockname(sock, (struct sockaddr*)&addr, &socklen) ||
- getnameinfo((struct sockaddr*)&addr, socklen, NULL, 0, (char*)Response->SecondaryAddress, sizeof(Response->SecondaryAddress), NI_NUMERICSERV))
- {
- portNumberSize = Response->SecondaryAddressLength = 0;
- }
- else
- {
- portNumberSize = strlen((char*)Response->SecondaryAddress) + 1;
- Response->SecondaryAddressLength = LE16(portNumberSize);
- }
-
- Response->MaxXmitFrag = Request->MaxXmitFrag;
- Response->MaxRecvFrag = Request->MaxRecvFrag;
- Response->AssocGroup = LE32(RpcAssocGroup);
-
- // This is really ugly (but efficient) code to support padding after the secondary address field
- if (portNumberSize < 3)
- {
- Response = (RPC_BIND_RESPONSE*)((BYTE*)Response - 4);
- }
-
- Response->NumResults = Request->NumCtxItems;
-
- if (UseRpcNDR64)
- {
- for (i = 0; i < numCtxItems; i++)
- {
- if ( IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
- {
- /*if (packetType == RPC_PT_BIND_REQ)*/
- *NdrCtx = LE16(Request->CtxItems[i].ContextId);
- }
-
- if ( IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
- {
- IsNDR64possible = TRUE;
-
- /*if (packetType == RPC_PT_BIND_REQ)*/
- *Ndr64Ctx = LE16(Request->CtxItems[i].ContextId);
- }
- }
- }
-
- for (i = 0; i < numCtxItems; i++)
- {
- memset(&Response->Results[i].TransferSyntax, 0, sizeof(GUID));
-
- if ( !IsNDR64possible && IsEqualGUID((GUID*)TransferSyntaxNDR32, &Request->CtxItems[i].TransferSyntax) )
- {
- Response->Results[i].SyntaxVersion = LE32(2);
- Response->Results[i].AckResult =
- Response->Results[i].AckReason = RPC_BIND_ACCEPT;
- memcpy(&Response->Results[i].TransferSyntax, TransferSyntaxNDR32, sizeof(GUID));
-
- _st = TRUE;
- }
- else if ( IsNDR64possible && IsEqualGUID((GUID*)TransferSyntaxNDR64, &Request->CtxItems[i].TransferSyntax) )
- {
- Response->Results[i].SyntaxVersion = LE32(1);
- Response->Results[i].AckResult =
- Response->Results[i].AckReason = RPC_BIND_ACCEPT;
- memcpy(&Response->Results[i].TransferSyntax, TransferSyntaxNDR64, sizeof(GUID));
-
- _st = TRUE;
- }
- else if ( UseRpcBTFN && !memcmp(BindTimeFeatureNegotiation, (BYTE*)(&Request->CtxItems[i].TransferSyntax), 8) )
- {
- Response->Results[i].SyntaxVersion = 0;
- Response->Results[i].AckResult = RPC_BIND_ACK;
-
- // Features requested are actually encoded in the GUID
- Response->Results[i].AckReason =
- ((WORD*)(&Request->CtxItems[i].TransferSyntax))[4] &
- (RPC_BTFN_SEC_CONTEXT_MULTIPLEX | RPC_BTFN_KEEP_ORPHAN);
- }
- else
- {
- Response->Results[i].SyntaxVersion = 0;
- Response->Results[i].AckResult =
- Response->Results[i].AckReason = RPC_BIND_NACK; // Unsupported
- }
- }
-
- if ( !_st ) return 0;
-
- return sizeof(RPC_BIND_RESPONSE) + numCtxItems * sizeof(((RPC_BIND_RESPONSE *)0)->Results[0]) - (portNumberSize < 3 ? 4 : 0);
-}
-
-
-//
-// Main RPC handling routine
-//
-typedef unsigned int (*GetResponseSize_t)(const void *const request, const unsigned int requestSize, WORD* NdrCtx, WORD* Ndr64Ctx);
-typedef int (*GetResponse_t)(const void* const request, void* response, const DWORD rpcAssocGroup, const SOCKET socket, WORD* NdrCtx, WORD* Ndr64Ctx, BYTE packetType, const char* const ipstr);
-
-static const struct {
- BYTE ResponsePacketType;
- GetResponseSize_t CheckRequestSize;
- GetResponse_t GetResponse;
-}
-_Actions[] = {
- { RPC_PT_BIND_ACK, (GetResponseSize_t)checkRpcBindSize, (GetResponse_t) rpcBind },
- { RPC_PT_RESPONSE, (GetResponseSize_t)checkRpcRequestSize, (GetResponse_t) rpcRequest },
- { RPC_PT_ALTERCONTEXT_ACK, (GetResponseSize_t)checkRpcBindSize, (GetResponse_t) rpcBind },
-};
-
-
-/*
- * This is the main RPC server loop. Returns after KMS request has been serviced
- * or a timeout has occured.
- */
-void rpcServer(const SOCKET sock, const DWORD RpcAssocGroup, const char* const ipstr)
-{
- RPC_HEADER rpcRequestHeader;
- WORD NdrCtx = INVALID_NDR_CTX, Ndr64Ctx = INVALID_NDR_CTX;
-
- randomNumberInit();
-
- while (_recv(sock, &rpcRequestHeader, sizeof(rpcRequestHeader)))
- {
- //int_fast8_t _st;
- unsigned int request_len, response_len;
- uint_fast8_t _a;
-
- #if defined(_PEDANTIC) && !defined(NO_LOG)
- checkRpcHeader(&rpcRequestHeader, rpcRequestHeader.PacketType, &logger);
- #endif // defined(_PEDANTIC) && !defined(NO_LOG)
-
- switch (rpcRequestHeader.PacketType)
- {
- case RPC_PT_BIND_REQ: _a = 0; break;
- case RPC_PT_REQUEST: _a = 1; break;
- case RPC_PT_ALTERCONTEXT_REQ: _a = 2; break;
- default: return;
- }
-
- request_len = LE16(rpcRequestHeader.FragLength) - sizeof(rpcRequestHeader);
-
- BYTE requestBuffer[MAX_REQUEST_SIZE + sizeof(RPC_RESPONSE64)];
- BYTE responseBuffer[MAX_RESPONSE_SIZE + sizeof(RPC_HEADER) + sizeof(RPC_RESPONSE64)];
-
- RPC_HEADER *rpcResponseHeader = (RPC_HEADER *)responseBuffer;
- RPC_RESPONSE* rpcResponse = (RPC_RESPONSE*)(responseBuffer + sizeof(rpcRequestHeader));
-
- // The request is larger than the buffer size
- if (request_len > MAX_REQUEST_SIZE + sizeof(RPC_REQUEST64)) return;
-
- // Unable to receive the complete request
- if (!_recv(sock, requestBuffer, request_len)) return;
-
- // Request is invalid
- if (!_Actions[_a].CheckRequestSize(requestBuffer, request_len, &NdrCtx, &Ndr64Ctx)) return;
-
- // Unable to create a valid response from request
- if (!(response_len = _Actions[_a].GetResponse(requestBuffer, rpcResponse, RpcAssocGroup, sock, &NdrCtx, &Ndr64Ctx, rpcRequestHeader.PacketType, ipstr))) return;
-
- response_len += sizeof(RPC_HEADER);
-
- memcpy(rpcResponseHeader, &rpcRequestHeader, sizeof(RPC_HEADER));
-
- rpcResponseHeader->FragLength = LE16(response_len);
- rpcResponseHeader->PacketType = _Actions[_a].ResponsePacketType;
-
- if (rpcResponseHeader->PacketType == RPC_PT_ALTERCONTEXT_ACK)
- rpcResponseHeader->PacketFlags = RPC_PF_FIRST | RPC_PF_LAST;
-
- if (!_send(sock, responseBuffer, response_len)) return;
-
- if (DisconnectImmediately && rpcResponseHeader->PacketType == RPC_PT_RESPONSE)
- shutdown(sock, VLMCSD_SHUT_RDWR);
- }
-}
-
-
-/* RPC client functions */
-
-static DWORD CallId = 2; // M$ starts with CallId 2. So we do the same.
-
-
-/*
- * Checks RPC header. Returns 0 on success.
- * This is mainly for debugging a non Microsoft KMS server that uses its own RPC code.
- */
-static int checkRpcHeader(const RPC_HEADER *const Header, const BYTE desiredPacketType, const PRINTFUNC p)
-{
- int status = 0;
-
- if (Header->PacketType != desiredPacketType)
- {
- p("Fatal: Received wrong RPC packet type. Expected %u but got %u\n",
- (uint32_t)desiredPacketType,
- Header->PacketType
- );
- status = !0;
- }
-
- if (Header->DataRepresentation != BE32(0x10000000))
- {
- p("Fatal: RPC response does not conform to Microsoft's limited support of DCE RPC\n");
- status = !0;
- }
-
- if (Header->AuthLength != 0)
- {
- p("Fatal: RPC response requests authentication\n");
- status = !0;
- }
-
- // vlmcsd does not support fragmented packets (not yet neccassary)
- if ( (Header->PacketFlags & (RPC_PF_FIRST | RPC_PF_LAST)) != (RPC_PF_FIRST | RPC_PF_LAST) )
- {
- p("Fatal: RPC packet flags RPC_PF_FIRST and RPC_PF_LAST are not both set.\n");
- status = !0;
- }
-
- if (Header->PacketFlags & RPC_PF_CANCEL_PENDING) p("Warning: %s should not be set\n", "RPC_PF_CANCEL_PENDING");
- if (Header->PacketFlags & RPC_PF_RESERVED) p("Warning: %s should not be set\n", "RPC_PF_RESERVED");
- if (Header->PacketFlags & RPC_PF_NOT_EXEC) p("Warning: %s should not be set\n", "RPC_PF_NOT_EXEC");
- if (Header->PacketFlags & RPC_PF_MAYBE) p("Warning: %s should not be set\n", "RPC_PF_MAYBE");
- if (Header->PacketFlags & RPC_PF_OBJECT) p("Warning: %s should not be set\n", "RPC_PF_OBJECT");
-
- if (Header->VersionMajor != 5 || Header->VersionMinor != 0)
- {
- p("Fatal: Expected RPC version 5.0 and got %u.%u\n", Header->VersionMajor, Header->VersionMinor);
- status = !0;
- }
-
- return status;
-}
-
-
-/*
- * Checks an RPC response header. Does basic header checks by calling checkRpcHeader()
- * and then does additional checks if response header complies with the respective request header.
- * PRINTFUNC p can be anything that has the same prototype as printf.
- * Returns 0 on success.
- */
-static int checkRpcResponseHeader(const RPC_HEADER *const ResponseHeader, const RPC_HEADER *const RequestHeader, const BYTE desiredPacketType, const PRINTFUNC p)
-{
- static int_fast8_t WineBugDetected = FALSE;
- int status = checkRpcHeader(ResponseHeader, desiredPacketType, p);
-
- if (desiredPacketType == RPC_PT_BIND_ACK)
- {
- if ((ResponseHeader->PacketFlags & RPC_PF_MULTIPLEX) != (RequestHeader->PacketFlags & RPC_PF_MULTIPLEX))
- {
- p("Warning: RPC_PF_MULTIPLEX of RPC request and response should match\n");
- }
- }
- else
- {
- if (ResponseHeader->PacketFlags & RPC_PF_MULTIPLEX)
- {
- p("Warning: %s should not be set\n", "RPC_PF_MULTIPLEX");
- }
- }
-
- if (!status && ResponseHeader->CallId == LE32(1))
- {
- if (!WineBugDetected)
- {
- p("Warning: Buggy RPC of Wine detected. Call Id of Response is always 1\n");
- WineBugDetected = TRUE;
- }
- }
- else if (ResponseHeader->CallId != RequestHeader->CallId)
- {
- p("Fatal: Sent Call Id %u but received answer for Call Id %u\n",
- (uint32_t)LE32(RequestHeader->CallId),
- (uint32_t)LE32(ResponseHeader->CallId)
- );
-
- status = !0;
- }
-
- return status;
-}
-
-/*
- * Initializes an RPC request header as needed for KMS, i.e. packet always fits in one fragment.
- * size cannot be greater than fragment length negotiated during RPC bind.
- */
-static void createRpcRequestHeader(RPC_HEADER* RequestHeader, BYTE packetType, WORD size)
-{
- RequestHeader->PacketType = packetType;
- RequestHeader->PacketFlags = RPC_PF_FIRST | RPC_PF_LAST;
- RequestHeader->VersionMajor = 5;
- RequestHeader->VersionMinor = 0;
- RequestHeader->AuthLength = 0;
- RequestHeader->DataRepresentation = BE32(0x10000000); // Little endian, ASCII charset, IEEE floating point
- RequestHeader->CallId = LE32(CallId);
- RequestHeader->FragLength = LE16(size);
-}
-
-
-/*
- * Sends a KMS request via RPC and receives a response.
- * Parameters are raw (encrypted) reqeuests / responses.
- * Returns 0 on success.
- */
-RpcStatus rpcSendRequest(const RpcCtx sock, const BYTE *const KmsRequest, const size_t requestSize, BYTE **KmsResponse, size_t *const responseSize)
-{
- #define MAX_EXCESS_BYTES 16
- RPC_HEADER *RequestHeader, ResponseHeader;
- RPC_REQUEST64 *RpcRequest;
- RPC_RESPONSE64 _Response;
- int status = 0;
- int_fast8_t useNdr64 = UseRpcNDR64 && firstPacketSent;
- size_t size = sizeof(RPC_HEADER) + (useNdr64 ? sizeof(RPC_REQUEST64) : sizeof(RPC_REQUEST)) + requestSize;
- size_t responseSize2;
-
- *KmsResponse = NULL;
-
- BYTE *_Request = (BYTE*)vlmcsd_malloc(size);
-
- RequestHeader = (RPC_HEADER*)_Request;
- RpcRequest = (RPC_REQUEST64*)(_Request + sizeof(RPC_HEADER));
-
- createRpcRequestHeader(RequestHeader, RPC_PT_REQUEST, size);
-
- // Increment CallId for next Request
- CallId++;
-
- RpcRequest->Opnum = 0;
-
- if (useNdr64)
- {
- RpcRequest->ContextId = LE16(1); // We negotiate NDR64 always as context 1
- RpcRequest->AllocHint = LE32(requestSize + sizeof(RpcRequest->Ndr64));
- RpcRequest->Ndr64.DataLength = LE64((uint64_t)requestSize);
- RpcRequest->Ndr64.DataSizeIs = LE64((uint64_t)requestSize);
- memcpy(RpcRequest->Ndr64.Data, KmsRequest, requestSize);
- }
- else
- {
- RpcRequest->ContextId = 0; // We negotiate NDR32 always as context 0
- RpcRequest->AllocHint = LE32(requestSize + sizeof(RpcRequest->Ndr));
- RpcRequest->Ndr.DataLength = LE32(requestSize);
- RpcRequest->Ndr.DataSizeIs = LE32(requestSize);
- memcpy(RpcRequest->Ndr.Data, KmsRequest, requestSize);
- }
-
- for(;;)
- {
- int bytesread;
-
- if (!_send(sock, _Request, size))
- {
- errorout("\nFatal: Could not send RPC request\n");
- status = !0;
- break;
- }
-
- if (!_recv(sock, &ResponseHeader, sizeof(RPC_HEADER)))
- {
- errorout("\nFatal: No RPC response received from server\n");
- status = !0;
- break;
- }
-
- if ((status = checkRpcResponseHeader(&ResponseHeader, RequestHeader, RPC_PT_RESPONSE, &errorout))) break;
-
- size = useNdr64 ? sizeof(RPC_RESPONSE64) : sizeof(RPC_RESPONSE);
-
- if (size > LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader))
- size = LE16(ResponseHeader.FragLength) - sizeof(ResponseHeader);
-
- if (!_recv(sock, &_Response, size))
- {
- errorout("\nFatal: RPC response is incomplete\n");
- status = !0;
- break;
- }
-
- if (_Response.CancelCount != 0)
- {
- errorout("\nFatal: RPC response cancel count is not 0\n");
- status = !0;
- }
-
- if (_Response.ContextId != (useNdr64 ? LE16(1) : 0))
- {
- errorout("\nFatal: RPC response context id %u is not bound\n", (unsigned int)LE16(_Response.ContextId));
- status = !0;
- }
-
- int_fast8_t sizesMatch;
-
- if (useNdr64)
- {
- *responseSize = (size_t)LE64(_Response.Ndr64.DataLength);
- responseSize2 = (size_t)LE64(_Response.Ndr64.DataSizeIs);
-
- if (!*responseSize || !_Response.Ndr64.DataSizeMax)
- {
- status = (int)LE32(_Response.Ndr64.status);
- break;
- }
-
- sizesMatch = (size_t)LE64(_Response.Ndr64.DataLength) == responseSize2;
- }
- else
- {
- *responseSize = (size_t)LE32(_Response.Ndr.DataLength);
- responseSize2 = (size_t)LE32(_Response.Ndr.DataSizeIs);
-
- if (!*responseSize || !_Response.Ndr.DataSizeMax)
- {
- status = (int)LE32(_Response.Ndr.status);
- break;
- }
-
- sizesMatch = (size_t)LE32(_Response.Ndr.DataLength) == responseSize2;
- }
-
- if (!sizesMatch)
- {
- errorout("\nFatal: NDR data length (%u) does not match NDR data size (%u)\n",
- (uint32_t)*responseSize,
- (uint32_t)LE32(_Response.Ndr.DataSizeIs)
- );
-
- status = !0;
- }
-
- *KmsResponse = (BYTE*)vlmcsd_malloc(*responseSize + MAX_EXCESS_BYTES);
-
- // If RPC stub is too short, assume missing bytes are zero (same ill behavior as MS RPC)
- memset(*KmsResponse, 0, *responseSize + MAX_EXCESS_BYTES);
-
- // Read up to 16 bytes more than bytes expected to detect faulty KMS emulators
- if ((bytesread = recv(sock, (char*)*KmsResponse, *responseSize + MAX_EXCESS_BYTES, 0)) < (int)*responseSize)
- {
- errorout("\nFatal: No or incomplete KMS response received. Required %u bytes but only got %i\n",
- (uint32_t)*responseSize,
- (int32_t)(bytesread < 0 ? 0 : bytesread)
- );
-
- status = !0;
- break;
- }
-
- DWORD *pReturnCode;
-
- size_t len = *responseSize + (useNdr64 ? sizeof(_Response.Ndr64) : sizeof(_Response.Ndr)) + sizeof(*pReturnCode);
- size_t pad = ((~len & 3) + 1) & 3;
-
- if (len + pad != LE32(_Response.AllocHint))
- {
- errorout("\nWarning: RPC stub size is %u, should be %u (probably incorrect padding)\n", (uint32_t)LE32(_Response.AllocHint), (uint32_t)(len + pad));
- }
- else
- {
- size_t i;
- for (i = 0; i < pad; i++)
- {
- if (*(*KmsResponse + *responseSize + sizeof(*pReturnCode) + i))
- {
- errorout("\nWarning: RPC stub data not padded to zeros according to Microsoft standard\n");
- break;
- }
- }
- }
-
- pReturnCode = (DWORD*)(*KmsResponse + *responseSize + pad);
- status = LE32(UA32(pReturnCode));
-
- if (status) errorout("\nWarning: RPC stub data reported Error %u\n", (uint32_t)status);
-
- break;
- }
-
- free(_Request);
- firstPacketSent = TRUE;
- return status;
- #undef MAX_EXCESS_BYTES
-}
-
-
-static int_fast8_t IsNullGuid(BYTE* guidPtr)
-{
- int_fast8_t i;
-
- for (i = 0; i < 16; i++)
- {
- if (guidPtr[i]) return FALSE;
- }
-
- return TRUE;
-}
-
-/*
- * Perform RPC client bind. Accepts a connected client socket.
- * Returns 0 on success. RPC binding is required before any payload can be
- * exchanged. It negotiates about protocol details.
- */
-RpcStatus rpcBindOrAlterClientContext(const RpcCtx sock, BYTE packetType, const int_fast8_t verbose)
-{
- RPC_HEADER *RequestHeader, ResponseHeader;
- RPC_BIND_REQUEST *bindRequest;
- RPC_BIND_RESPONSE *bindResponse;
- int status;
- WORD ctxItems = 1 + (packetType == RPC_PT_BIND_REQ ? UseRpcNDR64 + UseRpcBTFN : 0);
- size_t rpcBindSize = (sizeof(RPC_HEADER) + sizeof(RPC_BIND_REQUEST) + (ctxItems - 1) * sizeof(bindRequest->CtxItems[0]));
- WORD ctxIndex = 0;
- WORD i;
- WORD CtxBTFN = (WORD)~0, CtxNDR64 = (WORD)~0;
- BYTE _Request[rpcBindSize];
-
- RequestHeader = (RPC_HEADER*)_Request;
- bindRequest = (RPC_BIND_REQUEST* )(_Request + sizeof(RPC_HEADER));
-
- createRpcRequestHeader(RequestHeader, packetType, rpcBindSize);
- RequestHeader->PacketFlags |= UseMultiplexedRpc ? RPC_PF_MULTIPLEX : 0;
-
- bindRequest->AssocGroup = 0;
- bindRequest->MaxRecvFrag = bindRequest->MaxXmitFrag = LE16(5840);
- bindRequest->NumCtxItems = LE32(ctxItems);
-
- // data that is identical in all Ctx items
- for (i = 0; i < ctxItems; i++)
- {
- bindRequest->CtxItems[i].ContextId = LE16(i);
- bindRequest->CtxItems[i].InterfaceVerMajor = LE16(1);
- bindRequest->CtxItems[i].InterfaceVerMinor = 0;
- bindRequest->CtxItems[i].NumTransItems = LE16(1);
- bindRequest->CtxItems[i].SyntaxVersion = i ? LE32(1) : LE32(2);
-
- memcpy(&bindRequest->CtxItems[i].InterfaceUUID, InterfaceUuid, sizeof(GUID));
- }
-
- memcpy(&bindRequest->CtxItems[0].TransferSyntax, TransferSyntaxNDR32, sizeof(GUID));
-
- if (UseRpcNDR64 && packetType == RPC_PT_BIND_REQ)
- {
- memcpy(&bindRequest->CtxItems[++ctxIndex].TransferSyntax, TransferSyntaxNDR64, sizeof(GUID));
- CtxNDR64 = ctxIndex;
- }
-
- if (UseRpcBTFN && packetType == RPC_PT_BIND_REQ)
- {
- memcpy(&bindRequest->CtxItems[++ctxIndex].TransferSyntax, BindTimeFeatureNegotiation, sizeof(GUID));
- CtxBTFN = ctxIndex;
- }
-
- if (!_send(sock, _Request, rpcBindSize))
- {
- errorout("\nFatal: Sending RPC bind request failed\n");
- return !0;
- }
-
- if (!_recv(sock, &ResponseHeader, sizeof(RPC_HEADER)))
- {
- errorout("\nFatal: Did not receive a response from server\n");
- return !0;
- }
-
- if ((status = checkRpcResponseHeader
- (
- &ResponseHeader,
- RequestHeader,
- packetType == RPC_PT_BIND_REQ ? RPC_PT_BIND_ACK : RPC_PT_ALTERCONTEXT_ACK,
- &errorout
- )))
- {
- return status;
- }
-
- bindResponse = (RPC_BIND_RESPONSE*)vlmcsd_malloc(LE16(ResponseHeader.FragLength) - sizeof(RPC_HEADER));
- BYTE* bindResponseBytePtr = (BYTE*)bindResponse;
-
- if (!_recv(sock, bindResponse, LE16(ResponseHeader.FragLength) - sizeof(RPC_HEADER)))
- {
- errorout("\nFatal: Incomplete RPC bind acknowledgement received\n");
- free(bindResponseBytePtr);
- return !0;
- }
- else
- {
- /*
- * checking, whether a bind or alter context response is as expected.
- * This check is very strict and checks whether a KMS emulator behaves exactly the same way
- * as Microsoft's RPC does.
- */
- status = 0;
-
- if (bindResponse->SecondaryAddressLength < LE16(3))
- bindResponse = (RPC_BIND_RESPONSE*)(bindResponseBytePtr - 4);
-
- if (bindResponse->NumResults != bindRequest->NumCtxItems)
- {
- errorout("\nFatal: Expected %u CTX items but got %u\n",
- (uint32_t)LE32(bindRequest->NumCtxItems),
- (uint32_t)LE32(bindResponse->NumResults)
- );
-
- status = !0;
- }
-
- for (i = 0; i < ctxItems; i++)
- {
- const char* transferSyntaxName =
- i == CtxBTFN ? "BTFN" : i == CtxNDR64 ? "NDR64" : "NDR32";
-
- if (bindResponse->Results[i].AckResult == RPC_BIND_NACK) // transfer syntax was declined
- {
- if (!IsNullGuid((BYTE*)&bindResponse->Results[i].TransferSyntax))
- {
- errorout(
- "\nWarning: Rejected transfer syntax %s did not return NULL Guid\n",
- transferSyntaxName
- );
- }
-
- if (bindResponse->Results[i].SyntaxVersion)
- {
- errorout(
- "\nWarning: Rejected transfer syntax %s did not return syntax version 0 but %u\n",
- transferSyntaxName,
- LE32(bindResponse->Results[i].SyntaxVersion)
- );
- }
-
- if (bindResponse->Results[i].AckReason == RPC_ABSTRACTSYNTAX_UNSUPPORTED)
- {
- errorout(
- "\nWarning: Transfer syntax %s does not support KMS activation\n",
- transferSyntaxName
- );
- }
- else if (bindResponse->Results[i].AckReason != RPC_SYNTAX_UNSUPPORTED)
- {
- errorout(
- "\nWarning: Rejected transfer syntax %s did not return ack reason RPC_SYNTAX_UNSUPPORTED\n",
- transferSyntaxName
- );
- }
-
- continue;
- }
-
- if (i == CtxBTFN) // BTFN
- {
- if (bindResponse->Results[i].AckResult != RPC_BIND_ACK)
- {
- errorout("\nWarning: BTFN did not respond with RPC_BIND_ACK or RPC_BIND_NACK\n");
- }
-
- if (bindResponse->Results[i].AckReason != LE16(3))
- {
- errorout("\nWarning: BTFN did not return expected feature mask 0x3 but 0x%X\n", (unsigned int)LE16(bindResponse->Results[i].AckReason));
- }
-
- if (verbose) printf("... BTFN ");
- RpcFlags.HasBTFN = TRUE;
-
- continue;
- }
-
- // NDR32 or NDR64 Ctx
- if (bindResponse->Results[i].AckResult != RPC_BIND_ACCEPT)
- {
- errorout(
- "\nFatal: transfer syntax %s returned an invalid status, neither RPC_BIND_ACCEPT nor RPC_BIND_NACK\n",
- transferSyntaxName
- );
-
- status = !0;
- }
-
- if (!IsEqualGUID(&bindResponse->Results[i].TransferSyntax, &bindRequest->CtxItems[i].TransferSyntax))
- {
- errorout(
- "\nFatal: Transfer syntax of RPC bind request and response does not match\n"
- );
-
- status = !0;
- }
-
- if (bindResponse->Results[i].SyntaxVersion != bindRequest->CtxItems[i].SyntaxVersion)
- {
- errorout("\nFatal: Expected transfer syntax version %u for %s but got %u\n",
- (uint32_t)LE32(bindRequest->CtxItems[0].SyntaxVersion),
- transferSyntaxName,
- (uint32_t)LE32(bindResponse->Results[0].SyntaxVersion)
- );
-
- status = !0;
- }
-
- // The ack reason field is actually undefined here but Microsoft sets this to 0
- if (bindResponse->Results[i].AckReason != 0)
- {
- errorout(
- "\nWarning: Ack reason should be 0 but is %u\n",
- LE16(bindResponse->Results[i].AckReason)
- );
- }
-
- if (!status)
- {
- if (i == CtxNDR64)
- {
- RpcFlags.HasNDR64 = TRUE;
- if (verbose) printf("... NDR64 ");
- }
- if (!i)
- {
- RpcFlags.HasNDR32 = TRUE;
- if (verbose) printf("... NDR32 ");
- }
-
- }
- }
- }
-
- free(bindResponseBytePtr);
-
- if (!RpcFlags.HasNDR64 && !RpcFlags.HasNDR32)
- {
- errorout("\nFatal: Could neither negotiate NDR32 nor NDR64 with the RPC server\n");
- status = !0;
- }
-
- return status;
-}
-
-RpcStatus rpcBindClient(const RpcCtx sock, const int_fast8_t verbose)
-{
- firstPacketSent = FALSE;
- RpcFlags.mask = 0;
-
- RpcStatus status =
- rpcBindOrAlterClientContext(sock, RPC_PT_BIND_REQ, verbose);
-
- if (status) return status;
-
- if (!RpcFlags.HasNDR32)
- status = rpcBindOrAlterClientContext(sock, RPC_PT_ALTERCONTEXT_REQ, verbose);
-
- return status;
-}
-
-#endif // USE_MSRPC
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#if !defined(_CRYPTO_OPENSSL) && !defined(_CRYPTO_POLARSSL) && !defined(_CRYPTO_WINDOWS)
-#include "crypto_internal.h"
-#include "endian.h"
-
-#define F0(x, y, z) ( ((x) & (y)) | (~(x) & (z)) )
-#define F1(x, y, z) ( ((x) & (y)) | ((x) & (z)) | ((y) & (z)) )
-
-#define SI1(x) ( ROR32(x, 2 ) ^ ROR32(x, 13) ^ ROR32(x, 22) )
-#define SI2(x) ( ROR32(x, 6 ) ^ ROR32(x, 11) ^ ROR32(x, 25) )
-#define SI3(x) ( ROR32(x, 7 ) ^ ROR32(x, 18) ^ ((x) >> 3 ) )
-#define SI4(x) ( ROR32(x, 17) ^ ROR32(x, 19) ^ ((x) >> 10) )
-
-static const DWORD k[] = {
- 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1,
- 0x923F82A4, 0xAB1C5ED5, 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
- 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, 0xE49B69C1, 0xEFBE4786,
- 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
- 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147,
- 0x06CA6351, 0x14292967, 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
- 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, 0xA2BFE8A1, 0xA81A664B,
- 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
- 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A,
- 0x5B9CCA4F, 0x682E6FF3, 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
- 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
-};
-
-
-static void Sha256Init(Sha256Ctx *Ctx)
-{
- Ctx->State[0] = 0x6A09E667;
- Ctx->State[1] = 0xBB67AE85;
- Ctx->State[2] = 0x3C6EF372;
- Ctx->State[3] = 0xA54FF53A;
- Ctx->State[4] = 0x510E527F;
- Ctx->State[5] = 0x9B05688C;
- Ctx->State[6] = 0x1F83D9AB;
- Ctx->State[7] = 0x5BE0CD19;
- Ctx->Len = 0;
-}
-
-
-static void Sha256ProcessBlock(Sha256Ctx *Ctx, BYTE *block)
-{
- unsigned int i;
- DWORD w[64], temp1, temp2;
- DWORD a = Ctx->State[0];
- DWORD b = Ctx->State[1];
- DWORD c = Ctx->State[2];
- DWORD d = Ctx->State[3];
- DWORD e = Ctx->State[4];
- DWORD f = Ctx->State[5];
- DWORD g = Ctx->State[6];
- DWORD h = Ctx->State[7];
-
- for (i = 0; i < 16; i++)
- //w[ i ] = GET_UAA32BE(block, i);
- w[i] = BE32(((DWORD*)block)[i]);
-
- for (i = 16; i < 64; i++)
- w[ i ] = SI4(w[ i - 2 ]) + w[ i - 7 ] + SI3(w[ i - 15 ]) + w[ i - 16 ];
-
- for (i = 0; i < 64; i++)
- {
- temp1 = h + SI2(e) + F0(e, f, g) + k[ i ] + w[ i ];
- temp2 = SI1(a) + F1(a, b, c);
-
- h = g;
- g = f;
- f = e;
- e = d + temp1;
- d = c;
- c = b;
- b = a;
- a = temp1 + temp2;
- }
-
- Ctx->State[0] += a;
- Ctx->State[1] += b;
- Ctx->State[2] += c;
- Ctx->State[3] += d;
- Ctx->State[4] += e;
- Ctx->State[5] += f;
- Ctx->State[6] += g;
- Ctx->State[7] += h;
-}
-
-
-static void Sha256Update(Sha256Ctx *Ctx, BYTE *data, size_t len)
-{
- unsigned int b_len = Ctx->Len & 63,
- r_len = (b_len ^ 63) + 1;
-
- Ctx->Len += len;
-
- if ( len < r_len )
- {
- memcpy(Ctx->Buffer + b_len, data, len);
- return;
- }
-
- if ( r_len < 64 )
- {
- memcpy(Ctx->Buffer + b_len, data, r_len);
- len -= r_len;
- data += r_len;
- Sha256ProcessBlock(Ctx, Ctx->Buffer);
- }
-
- for (; len >= 64; len -= 64, data += 64)
- Sha256ProcessBlock(Ctx, data);
-
- if ( len ) memcpy(Ctx->Buffer, data, len);
-}
-
-
-static void Sha256Finish(Sha256Ctx *Ctx, BYTE *hash)
-{
- unsigned int i, b_len = Ctx->Len & 63;
-
- Ctx->Buffer[ b_len ] = 0x80;
- if ( b_len ^ 63 ) memset(Ctx->Buffer + b_len + 1, 0, b_len ^ 63);
-
- if ( b_len >= 56 )
- {
- Sha256ProcessBlock(Ctx, Ctx->Buffer);
- memset(Ctx->Buffer, 0, 56);
- }
-
- //PUT_UAA64BE(Ctx->Buffer, (unsigned long long)(Ctx->Len * 8), 7);
- ((uint64_t*)Ctx->Buffer)[7] = BE64((uint64_t)Ctx->Len << 3);
- Sha256ProcessBlock(Ctx, Ctx->Buffer);
-
- for (i = 0; i < 8; i++)
- //PUT_UAA32BE(hash, Ctx->State[i], i);
- ((DWORD*)hash)[i] = BE32(Ctx->State[i]);
-
-}
-
-
-void Sha256(BYTE *data, size_t len, BYTE *hash)
-{
- Sha256Ctx Ctx;
-
- Sha256Init(&Ctx);
- Sha256Update(&Ctx, data, len);
- Sha256Finish(&Ctx, hash);
-}
-
-
-static void _Sha256HmacInit(Sha256HmacCtx *Ctx, BYTE *key, size_t klen)
-{
- BYTE IPad[64];
- unsigned int i;
-
- memset(IPad, 0x36, sizeof(IPad));
- memset(Ctx->OPad, 0x5C, sizeof(Ctx->OPad));
-
- if ( klen > 64 )
- {
- BYTE *temp = (BYTE*)alloca(32);
- Sha256(key, klen, temp);
- klen = 32;
- key = temp;
- }
-
- for (i = 0; i < klen; i++)
- {
- IPad[ i ] ^= key[ i ];
- Ctx->OPad[ i ] ^= key[ i ];
- }
-
- Sha256Init(&Ctx->ShaCtx);
- Sha256Update(&Ctx->ShaCtx, IPad, sizeof(IPad));
-}
-
-
-static void _Sha256HmacUpdate(Sha256HmacCtx *Ctx, BYTE *data, size_t len)
-{
- Sha256Update(&Ctx->ShaCtx, data, len);
-}
-
-
-static void _Sha256HmacFinish(Sha256HmacCtx *Ctx, BYTE *hmac)
-{
- BYTE temp[32];
-
- Sha256Finish(&Ctx->ShaCtx, temp);
- Sha256Init(&Ctx->ShaCtx);
- Sha256Update(&Ctx->ShaCtx, Ctx->OPad, sizeof(Ctx->OPad));
- Sha256Update(&Ctx->ShaCtx, temp, sizeof(temp));
- Sha256Finish(&Ctx->ShaCtx, hmac);
-}
-
-
-
-int_fast8_t Sha256Hmac(BYTE* key, BYTE* restrict data, DWORD len, BYTE* restrict hmac)
-{
- Sha256HmacCtx Ctx;
- _Sha256HmacInit(&Ctx, key, 16);
- _Sha256HmacUpdate(&Ctx, data, len);
- _Sha256HmacFinish(&Ctx, hmac);
- return TRUE;
-}
-
-
-#endif // No external Crypto
-
-/*
- * dns_srv.c
- *
- * This file contains the code for KMS SRV record lookup in DNS (_vlmcs._tcp.example.com IN SRV 0 0 1688 mykms.example.com)
- *
- */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifndef NO_DNS
-
-#include "dns_srv.h"
-
-#include
-#include
-#ifndef _WIN32
-#include
-#include
-#include
-#include
-#include
-//#ifndef DNS_PARSER_INTERNAL
-#if __ANDROID__
-#include
-#include "nameser.h"
-#include "resolv.h"
-#else // other Unix non-Android
-#include
-#include
-#include
-#endif // other Unix non-Android
-//#endif // DNS_PARSER_INTERNAL
-#else // WIN32
-#include
-#endif // WIN32
-
-#include "helpers.h"
-#include "output.h"
-#include "endian.h"
-
-#if defined(DNS_PARSER_INTERNAL) && !defined(_WIN32)
-
-#include "ns_name.h"
-#include "ns_parse.h"
-
-// Define macros to redirect DNS parser functions to internal versions
-
-#undef ns_msg
-#undef ns_initparse
-#undef ns_parserr
-#undef ns_rr
-#undef ns_name_uncompress
-#undef ns_msg_base
-#undef ns_msg_end
-#undef ns_rr_rdata
-#undef ns_rr_type
-#undef ns_msg_count
-#undef ns_rr_class
-#undef ns_s_an
-#define ns_msg ns_msg_vlmcsd
-#define ns_initparse ns_initparse_vlmcsd
-#define ns_parserr ns_parserr_vlmcsd
-#define ns_rr ns_rr_vlmcsd
-#define ns_name_uncompress ns_name_uncompress_vlmcsd
-#define ns_msg_base ns_msg_base_vlmcsd
-#define ns_msg_end ns_msg_end_vlmcsd
-#define ns_rr_rdata ns_rr_rdata_vlmcsd
-#define ns_rr_type ns_rr_type_vlmcsd
-#define ns_msg_count ns_msg_count_vlmcsd
-#define ns_rr_class ns_rr_class_vlmcsd
-#define ns_s_an ns_s_an_vlmcsd
-
-#ifndef NS_MAXLABEL
-#define NS_MAXLABEL 63
-#endif
-
-#endif // defined(DNS_PARSER_INTERNAL) && !defined(_WIN32)
-
-
-//TODO: maybe move to helpers.c
-static unsigned int isqrt(unsigned int n)
-{
- unsigned int c = 0x8000;
- unsigned int g = 0x8000;
-
- for(;;)
- {
- if(g*g > n)
- g ^= c;
-
- c >>= 1;
-
- if(c == 0) return g;
-
- g |= c;
- }
-}
-
-
-/*
- * Compare function for qsort to sort SRV records by priority and weight
- * random_weight must be product of weight from SRV record and square root of a random number
- */
-static int kmsServerListCompareFunc1(const void* a, const void* b)
-{
- if ( !a && !b) return 0;
- if ( a && !b) return -1;
- if ( !a && b) return 1;
-
- int priority_order = (int)((*(kms_server_dns_ptr*)a)->priority) - ((int)(*(kms_server_dns_ptr*)b)->priority);
-
- if (priority_order) return priority_order;
-
- return (int)((*(kms_server_dns_ptr*)b)->random_weight) - ((int)(*(kms_server_dns_ptr*)a)->random_weight);
-}
-
-/* Sort resulting SRV records */
-void sortSrvRecords(kms_server_dns_ptr* serverlist, const int answers)
-{
- int i;
-
- for (i = 0; i < answers; i++)
- {
- serverlist[i]->random_weight = (rand32() % 256) * isqrt(serverlist[i]->weight * 1000);
- }
-
- qsort(serverlist, answers, sizeof(kms_server_dns_ptr), kmsServerListCompareFunc1);
-}
-
-
-#define RECEIVE_BUFFER_SIZE 2048
-#ifndef _WIN32 // UNIX resolver
-
-/*
- * Retrieves a raw DNS answer (a buffer of what came over the net)
- * Result must be parsed
- */
-static int getDnsRawAnswer(const char *restrict query, unsigned char** receive_buffer)
-{
- if (res_init() < 0)
- {
- errorout("Cannot initialize resolver: %s", strerror(errno));
- return 0;
- }
-
- //if(!(*receive_buffer = (unsigned char*)malloc(RECEIVE_BUFFER_SIZE))) OutOfMemory();
- *receive_buffer = (unsigned char*)vlmcsd_malloc(RECEIVE_BUFFER_SIZE);
-
- int bytes_received;
-
- if (*query == '.')
- {
-# if __ANDROID__ || __GLIBC__ /* including __UCLIBC__*/ || __APPLE__ || __CYGWIN__ || __FreeBSD__ || __NetBSD__ || __DragonFly__ || __OpenBSD__ || __sun__
- bytes_received = res_querydomain("_vlmcs._tcp", query + 1, ns_c_in, ns_t_srv, *receive_buffer, RECEIVE_BUFFER_SIZE);
-# else
- char* querystring = (char*)alloca(strlen(query) + 12);
- strcpy(querystring, "_vlmcs._tcp");
- strcat(querystring, query);
- bytes_received = res_query(querystring, ns_c_in, ns_t_srv, *receive_buffer, RECEIVE_BUFFER_SIZE);
-# endif
- }
- else
- {
- bytes_received = res_search("_vlmcs._tcp", ns_c_in, ns_t_srv, *receive_buffer, RECEIVE_BUFFER_SIZE);
- }
-
- if (bytes_received < 0)
- {
- errorout("Fatal: DNS query to %s%s failed: %s\n", "_vlmcs._tcp", *query == '.' ? query : "", hstrerror(h_errno));
- return 0;
- }
-
- return bytes_received;
-}
-
-/*
- * Retrieves an unsorted array of SRV records (Unix / Posix)
- */
-int getKmsServerList(kms_server_dns_ptr** serverlist, const char *restrict query)
-{
- unsigned char* receive_buffer;
- *serverlist = NULL;
-
- int bytes_received = getDnsRawAnswer(query, &receive_buffer);
-
- if (bytes_received == 0) return 0;
-
- ns_msg msg;
-
- if (ns_initparse(receive_buffer, bytes_received, &msg) < 0)
- {
- errorout("Fatal: Incorrect DNS response: %s\n", strerror(errno));
- free(receive_buffer);
- return 0;
- }
-
- uint16_t i, answers = ns_msg_count(msg, ns_s_an);
- //if(!(*serverlist = (kms_server_dns_ptr*)malloc(answers * sizeof(kms_server_dns_ptr)))) OutOfMemory();
- *serverlist = (kms_server_dns_ptr*)malloc(answers * sizeof(kms_server_dns_ptr));
-
- memset(*serverlist, 0, answers * sizeof(kms_server_dns_ptr));
-
- for (i = 0; i < answers; i++)
- {
- ns_rr rr;
-
- if (ns_parserr(&msg, ns_s_an, i, &rr) < 0)
- {
- errorout("Warning: Error in DNS resource record: %s\n", strerror(errno));
- continue;
- }
-
- if (ns_rr_type(rr) != ns_t_srv)
- {
- errorout("Warning: DNS server returned non-SRV record\n");
- continue;
- }
-
- if (ns_rr_class(rr) != ns_c_in)
- {
- errorout("Warning: DNS server returned non-IN class record\n");
- continue;
- }
-
- dns_srv_record_ptr srvrecord = (dns_srv_record_ptr)ns_rr_rdata(rr);
- kms_server_dns_ptr kms_server = (kms_server_dns_ptr)vlmcsd_malloc(sizeof(kms_server_dns_t));
-
- (*serverlist)[i] = kms_server;
-
- if (ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg), srvrecord->name, kms_server->serverName, sizeof(kms_server->serverName)) < 0)
- {
- errorout("Warning: No valid DNS name returned in SRV record: %s\n", strerror(errno));
- continue;
- }
-
- sprintf(kms_server->serverName + strlen(kms_server->serverName), ":%hu", GET_UA16BE(&srvrecord->port));
- kms_server->priority = GET_UA16BE(&srvrecord->priority);
- kms_server->weight = GET_UA16BE(&srvrecord->weight);
-
- }
-
- free(receive_buffer);
- return answers;
-}
-
-#else // WIN32 (Windows Resolver)
-
-/*
- * Retrieves an unsorted array of SRV records (Windows)
- */
-int getKmsServerList(kms_server_dns_ptr** serverlist, const char *const restrict query)
-{
-# define MAX_DNS_NAME_SIZE 254
- *serverlist = NULL;
- PDNS_RECORD receive_buffer;
- char dnsDomain[MAX_DNS_NAME_SIZE];
- char FqdnQuery[MAX_DNS_NAME_SIZE];
- DWORD size = MAX_DNS_NAME_SIZE;
- DNS_STATUS result;
- int answers = 0;
- PDNS_RECORD dns_iterator;
-
- if (*query == '-')
- {
- if (!GetComputerNameExA(ComputerNamePhysicalDnsDomain, dnsDomain, &size))
- {
- errorout("Fatal: Could not determine computer's DNS name: %s\n", vlmcsd_strerror(GetLastError()));
- return 0;
- }
-
- strcpy(FqdnQuery, "_vlmcs._tcp.");
- strncat(FqdnQuery, dnsDomain, MAX_DNS_NAME_SIZE - 12);
- }
- else
- {
- strcpy(FqdnQuery, "_vlmcs._tcp");
- strncat(FqdnQuery, query, MAX_DNS_NAME_SIZE - 11);
- }
-
- if ((result = DnsQuery_UTF8(FqdnQuery, DNS_TYPE_SRV, 0, NULL, &receive_buffer, NULL)) != 0)
- {
- errorout("Fatal: DNS query to %s failed: %s\n", FqdnQuery, vlmcsd_strerror(result));
- return 0;
- }
-
- for (dns_iterator = receive_buffer; dns_iterator; dns_iterator = dns_iterator->pNext)
- {
- if (dns_iterator->Flags.S.Section != 1) continue;
-
- if (dns_iterator->wType != DNS_TYPE_SRV)
- {
- errorout("Warning: DNS server returned non-SRV record\n");
- continue;
- }
-
- answers++;
- }
-
- *serverlist = (kms_server_dns_ptr*)vlmcsd_malloc(answers * sizeof(kms_server_dns_ptr));
-
- for (answers = 0, dns_iterator = receive_buffer; dns_iterator; dns_iterator = dns_iterator->pNext)
- {
- if (dns_iterator->wType != DNS_TYPE_SRV) continue;
-
- kms_server_dns_ptr kms_server = (kms_server_dns_ptr)vlmcsd_malloc(sizeof(kms_server_dns_t));
-
- memset(kms_server, 0, sizeof(kms_server_dns_t));
-
- snprintf(kms_server->serverName, sizeof(kms_server->serverName), "%s:%hu", dns_iterator->Data.SRV.pNameTarget, dns_iterator->Data.SRV.wPort);
- kms_server->priority = dns_iterator->Data.SRV.wPriority;
- kms_server->weight = dns_iterator->Data.SRV.wWeight;
-
- (*serverlist)[answers++] = kms_server;
- }
-
- //sortSrvRecords(*serverlist, answers, NoSrvRecordPriority);
-
- DnsRecordListFree(receive_buffer, DnsFreeRecordList);
-
- return answers;
-# undef MAX_DNS_NAME_SIZE
-}
-#endif // _WIN32
-#undef RECEIVE_BUFFER_SIZE
-#endif // NO_DNS
-
-
-/*
- * Copyright (c) 1996,1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Modified by Hotbird64 for use with vlmcs.
- */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifdef DNS_PARSER_INTERNAL
-#ifndef NO_DNS
-
-/* Import. */
-
-#include
-#include
-#include
-
-#include "types.h"
-#include "endian.h"
-#include "ns_name.h"
-#include "ns_parse.h"
-
-/* Macros. */
-
-#define NS_GET16_VLMCSD(s, cp) do { \
- (s) = GET_UA16BE(cp); \
- (cp) += NS_INT16SZ; \
-} while (0)
-
-#define NS_GET32_VLMCSD(l, cp) do { \
- (l) = GET_UA32BE(cp); \
- (cp) += NS_INT32SZ; \
-} while (0)
-
-#define RETERR(err) do { errno = (err); return (-1); } while (0)
-
-/* Forward. */
-
-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)
-{
- const unsigned char *p;
- for (p=s; p=192)
- {if (p+1 0; count--) {
- int b, rdlength;
-
- b = dn_skipname_vlmcsd(ptr, eom);
- if (b < 0)
- RETERR(EMSGSIZE);
- ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
- if (section != ns_s_qd_vlmcsd) {
- if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
- RETERR(EMSGSIZE);
- ptr += NS_INT32SZ/*TTL*/;
- NS_GET16_VLMCSD(rdlength, ptr);
- ptr += rdlength/*RData*/;
- }
- }
- if (ptr > eom)
- RETERR(EMSGSIZE);
- return (ptr - optr);
-}
-
-int
-ns_initparse_vlmcsd(const uint8_t *msg, int msglen, ns_msg_vlmcsd *handle) {
- const uint8_t *eom = msg + msglen;
- int i;
-
- memset(handle, 0x5e, sizeof *handle);
- handle->_msg = msg;
- handle->_eom = eom;
- if (msg + NS_INT16SZ > eom)
- RETERR(EMSGSIZE);
- NS_GET16_VLMCSD(handle->_id, msg);
- if (msg + NS_INT16SZ > eom)
- RETERR(EMSGSIZE);
- NS_GET16_VLMCSD(handle->_flags, msg);
- for (i = 0; i < ns_s_max_vlmcsd; i++) {
- if (msg + NS_INT16SZ > eom)
- RETERR(EMSGSIZE);
- NS_GET16_VLMCSD(handle->_counts[i], msg);
- }
- for (i = 0; i < ns_s_max_vlmcsd; i++)
- if (handle->_counts[i] == 0)
- handle->_sections[i] = NULL;
- else {
- int b = ns_skiprr_vlmcsd(msg, eom, (ns_sect_vlmcsd)i,
- handle->_counts[i]);
-
- if (b < 0)
- return (-1);
- handle->_sections[i] = msg;
- msg += b;
- }
- if (msg > eom)
- RETERR(EMSGSIZE);
- handle->_eom = msg;
- setsection_vlmcsd(handle, ns_s_max_vlmcsd);
- return (0);
-}
-
-int
-ns_parserr_vlmcsd(ns_msg_vlmcsd *handle, ns_sect_vlmcsd section, int rrnum, ns_rr_vlmcsd *rr) {
- int b;
-
- /* Make section right. */
- if (section >= ns_s_max_vlmcsd)
- RETERR(ENODEV);
- if (section != handle->_sect)
- setsection_vlmcsd(handle, section);
-
- /* Make rrnum right. */
- if (rrnum == -1)
- rrnum = handle->_rrnum;
- if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
- RETERR(ENODEV);
- if (rrnum < handle->_rrnum)
- setsection_vlmcsd(handle, section);
- if (rrnum > handle->_rrnum) {
- b = ns_skiprr_vlmcsd(handle->_msg_ptr, handle->_eom, section,
- rrnum - handle->_rrnum);
-
- if (b < 0)
- return (-1);
- handle->_msg_ptr += b;
- handle->_rrnum = rrnum;
- }
-
- /* Do the parse. */
- b = ns_name_uncompress_vlmcsd(handle->_msg, handle->_eom,
- handle->_msg_ptr, rr->name, NS_MAXDNAME);
- if (b < 0)
- return (-1);
- handle->_msg_ptr += b;
- if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
- RETERR(EMSGSIZE);
- NS_GET16_VLMCSD(rr->type, handle->_msg_ptr);
- NS_GET16_VLMCSD(rr->rr_class, handle->_msg_ptr);
- if (section == ns_s_qd_vlmcsd) {
- rr->ttl = 0;
- rr->rdlength = 0;
- rr->rdata = NULL;
- } else {
- if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
- RETERR(EMSGSIZE);
- NS_GET32_VLMCSD(rr->ttl, handle->_msg_ptr);
- NS_GET16_VLMCSD(rr->rdlength, handle->_msg_ptr);
- if (handle->_msg_ptr + rr->rdlength > handle->_eom)
- RETERR(EMSGSIZE);
- rr->rdata = handle->_msg_ptr;
- handle->_msg_ptr += rr->rdlength;
- }
- if (++handle->_rrnum > handle->_counts[(int)section])
- setsection_vlmcsd(handle, (ns_sect_vlmcsd)((int)section + 1));
-
- /* All done. */
- return (0);
-}
-
-/* Private. */
-
-static void
-setsection_vlmcsd(ns_msg_vlmcsd *msg, ns_sect_vlmcsd sect) {
- msg->_sect = sect;
- if (sect == ns_s_max_vlmcsd) {
- msg->_rrnum = -1;
- msg->_msg_ptr = NULL;
- } else {
- msg->_rrnum = 0;
- msg->_msg_ptr = msg->_sections[(int)sect];
- }
-}
-
-#endif // !NO_DNS
-#endif // DNS_PARSER_INTERNAL
-/*
- * Copyright (c) 1996,1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-/*
- * Modified by Hotbird64 for use with vlmcs.
- */
-
-#ifndef CONFIG
-#define CONFIG "config.h"
-#endif // CONFIG
-#include CONFIG
-
-#ifdef DNS_PARSER_INTERNAL
-#ifndef NO_DNS
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "types.h"
-#include "ns_name.h"
-
-#ifdef SPRINTF_CHAR
-# define SPRINTF(x) strlen(sprintf/**/x)
-#else
-# define SPRINTF(x) ((size_t)sprintf x)
-#endif
-
-#define NS_TYPE_ELT 0x40 /* EDNS0 extended label type */
-#define DNS_LABELTYPE_BITSTRING 0x41
-
-#define NS_MAXCDNAME 255
-#define NS_CMPRSFLGS 0xc0
-
-/* Data. */
-
-static char digits[] = "0123456789";
-
-
-/* Forward. */
-
-static int special_vlmcsd(int);
-static int printable_vlmcsd(int);
-static int labellen_vlmcsd(const uint8_t *);
-static int decode_bitstring_vlmcsd(const char **, char *, const char *);
-
-/*
- * ns_name_ntop(src, dst, dstsiz)
- * Convert an encoded domain name to printable ascii as per RFC1035.
- * return:
- * Number of bytes written to buffer, or -1 (with errno set)
- * notes:
- * The root is returned as "."
- * All other domains are returned in non absolute form
- */
-static int
-ns_name_ntop_vlmcsd(const uint8_t *src, char *dst, size_t dstsiz)
-{
- const uint8_t *cp;
- char *dn, *eom;
- uint8_t c;
- uint32_t n;
- int l;
-
- cp = src;
- dn = dst;
- eom = dst + dstsiz;
-
- while ((n = *cp++) != 0) {
- if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
- /* Some kind of compression pointer. */
- errno = EMSGSIZE;
- return (-1);
- }
- if (dn != dst) {
- if (dn >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '.';
- }
- if ((l = labellen_vlmcsd(cp - 1)) < 0) {
- errno = EMSGSIZE; /* XXX */
- return(-1);
- }
- if (dn + l >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
- int m;
-
- if (n != DNS_LABELTYPE_BITSTRING) {
- /* XXX: labellen should reject this case */
- errno = EINVAL;
- return(-1);
- }
- if ((m = decode_bitstring_vlmcsd((const char **)&cp, dn, eom)) < 0)
- {
- errno = EMSGSIZE;
- return(-1);
- }
- dn += m;
- continue;
- }
- for ((void)NULL; l > 0; l--) {
- c = *cp++;
- if (special_vlmcsd(c)) {
- if (dn + 1 >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '\\';
- *dn++ = (char)c;
- } else if (!printable_vlmcsd(c)) {
- if (dn + 3 >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '\\';
- *dn++ = digits[c / 100];
- *dn++ = digits[(c % 100) / 10];
- *dn++ = digits[c % 10];
- } else {
- if (dn >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = (char)c;
- }
- }
- }
- if (dn == dst) {
- if (dn >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '.';
- }
- if (dn >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- *dn++ = '\0';
- return (dn - dst);
-}
-
-static int
-ns_name_unpack_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src,
- uint8_t *dst, size_t dstsiz)
-{
- const uint8_t *srcp, *dstlim;
- uint8_t *dstp;
- int n, len, checked, l;
-
- len = -1;
- checked = 0;
- dstp = dst;
- srcp = src;
- dstlim = dst + dstsiz;
- if (srcp < msg || srcp >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- /* Fetch next label in domain name. */
- while ((n = *srcp++) != 0) {
- /* Check for indirection. */
- switch (n & NS_CMPRSFLGS) {
- case 0:
- case NS_TYPE_ELT:
- /* Limit checks. */
- if ((l = labellen_vlmcsd(srcp - 1)) < 0) {
- errno = EMSGSIZE;
- return(-1);
- }
- if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- checked += l + 1;
- *dstp++ = n;
- memcpy(dstp, srcp, l);
- dstp += l;
- srcp += l;
- break;
-
- case NS_CMPRSFLGS:
- if (srcp >= eom) {
- errno = EMSGSIZE;
- return (-1);
- }
- if (len < 0)
- len = srcp - src + 1;
- srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
- if (srcp < msg || srcp >= eom) { /* Out of range. */
- errno = EMSGSIZE;
- return (-1);
- }
- checked += 2;
- /*
- * Check for loops in the compressed name;
- * if we've looked at the whole message,
- * there must be a loop.
- */
- if (checked >= eom - msg) {
- errno = EMSGSIZE;
- return (-1);
- }
- break;
-
- default:
- errno = EMSGSIZE;
- return (-1); /* flag error */
- }
- }
- *dstp = '\0';
- if (len < 0)
- len = srcp - src;
- return (len);
-}
-
-
-/*
- * ns_name_uncompress_vlmcsd(msg, eom, src, dst, dstsiz)
- * Expand compressed domain name to presentation format.
- * return:
- * Number of bytes read out of `src', or -1 (with errno set).
- * note:
- * Root domain returns as "." not "".
- */
-int
-ns_name_uncompress_vlmcsd(const uint8_t *msg, const uint8_t *eom, const uint8_t *src,
- char *dst, size_t dstsiz)
-{
- uint8_t tmp[NS_MAXCDNAME];
- int n;
-
- if ((n = ns_name_unpack_vlmcsd(msg, eom, src, tmp, sizeof tmp)) == -1)
- return (-1);
- if (ns_name_ntop_vlmcsd(tmp, dst, dstsiz) == -1)
- return (-1);
- return (n);
-}
-
-/*
- * special(ch)
- * Thinking in noninternationalized USASCII (per the DNS spec),
- * is this characted special ("in need of quoting") ?
- * return:
- * boolean.
- */
-static int
-special_vlmcsd(int ch) {
- switch (ch) {
- case 0x22: /* '"' */
- case 0x2E: /* '.' */
- case 0x3B: /* ';' */
- case 0x5C: /* '\\' */
- case 0x28: /* '(' */
- case 0x29: /* ')' */
- /* Special modifiers in zone files. */
- case 0x40: /* '@' */
- case 0x24: /* '$' */
- return (1);
- default:
- return (0);
- }
-}
-
-/*
- * printable(ch)
- * Thinking in noninternationalized USASCII (per the DNS spec),
- * is this character visible and not a space when printed ?
- * return:
- * boolean.
- */
-static int
-printable_vlmcsd(int ch) {
- return (ch > 0x20 && ch < 0x7f);
-}
-
-static int
-decode_bitstring_vlmcsd(const char **cpp, char *dn, const char *eom)
-{
- const char *cp = *cpp;
- char *beg = dn, tc;
- int b, blen, plen;
-
- if ((blen = (*cp & 0xff)) == 0)
- blen = 256;
- plen = (blen + 3) / 4;
- plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
- if (dn + plen >= eom)
- return(-1);
-
- cp++;
- dn += SPRINTF((dn, "\\[x"));
- for (b = blen; b > 7; b -= 8, cp++)
- dn += SPRINTF((dn, "%02x", *cp & 0xff));
- if (b > 4) {
- tc = *cp++;
- dn += SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
- } else if (b > 0) {
- tc = *cp++;
- dn += SPRINTF((dn, "%1x",
- ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
- }
- dn += SPRINTF((dn, "/%d]", blen));
-
- *cpp = cp;
- return(dn - beg);
-}
-
-static int
-labellen_vlmcsd(const uint8_t *lp)
-{
- int bitlen;
- uint8_t l = *lp;
-
- if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
- /* should be avoided by the caller */
- return(-1);
- }
-
- if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
- if (l == DNS_LABELTYPE_BITSTRING) {
- if ((bitlen = *(lp + 1)) == 0)
- bitlen = 256;
- return((bitlen + 7 ) / 8 + 1);
- }
- return(-1); /* unknwon ELT */
- }
- return(l);
-}
-
-#endif // !NO_DNS
-#endif // DNS_PARSER_INTERNAL