2015-11-29 17:30:52 +08:00
# ifndef CONFIG
# define CONFIG "config.h"
# endif // CONFIG
# include CONFIG
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
# include "vlmcs.h"
2016-10-08 13:35:48 +08:00
# if _MSC_VER
# include <Shlwapi.h>
# endif
2015-11-29 17:30:52 +08:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <errno.h>
# include <stdint.h>
2016-10-08 13:35:48 +08:00
# if _MSC_VER
# include "wingetopt.h"
# else
2015-11-29 17:30:52 +08:00
# include <getopt.h>
2016-10-08 13:35:48 +08:00
# endif
2015-11-29 17:30:52 +08:00
# include <sys/types.h>
# include <sys/stat.h>
2016-10-08 13:35:48 +08:00
# ifndef _MSC_VER
2015-11-29 17:30:52 +08:00
# include <unistd.h>
2016-10-08 13:35:48 +08:00
# endif
2015-11-29 17:30:52 +08:00
# ifndef _WIN32
# include <sys/ioctl.h>
# include <termios.h>
# 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
2016-08-15 18:35:59 +08:00
//#define kmsVersionMinor 0 // Currently constant. May change in future KMS versions
# ifndef IS_LIBRARY
2015-11-29 17:30:52 +08:00
// Function Prototypes
static void CreateRequestBase ( REQUEST * Request ) ;
// KMS Parameters
2016-06-06 10:36:00 +08:00
# ifndef NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
static int_fast8_t verbose = FALSE ;
2016-06-06 10:36:00 +08:00
# endif
2015-11-29 17:30:52 +08:00
static int_fast8_t VMInfo = FALSE ;
static int_fast8_t dnsnames = TRUE ;
static int FixedRequests = 0 ;
2016-08-15 18:35:59 +08:00
static DWORD LicenseStatus = 0x02 ;
2015-11-29 17:30:52 +08:00
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 ;
2016-08-15 18:35:59 +08:00
static int_fast16_t kmsVersionMinor = 0 ;
2016-09-04 22:03:54 +08:00
static const char * ePidGroup [ ] = { " Windows " , " Office2010 " , " Office2013 " , " Office2016 " } ;
2015-11-29 17:30:52 +08:00
# 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 ;
2016-09-04 22:03:54 +08:00
typedef char iniFileEpidLines [ 4 ] [ 256 ] ;
2015-11-29 17:30:52 +08:00
// Well known "license packs"
static const LicensePack LicensePackList [ ] =
{
// List of names min lics version appID skuId KMSCountedID
/* 000 */ { " Vista \000 W6 \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 \000 Windows7 \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 \000 Windows8 \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 \000 Windows8C \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 \000 Windows81 \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 \000 Windows81C \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 \000 Windows10 \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 \000 Windows10C \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 \000 O14 \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 \000 O15 \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] [ <host>[:<port>] | .<domain> | - ] [options] \n \n "
# else // DNS
" Usage: %s [options] [<host>[:<port>]] [options] \n \n "
# endif // DNS
" Options: \n \n "
2016-06-06 10:36:00 +08:00
# ifndef NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
" -v Be verbose \n "
2016-06-06 10:36:00 +08:00
# endif
2015-11-29 17:30:52 +08:00
" -l <app> \n "
" -4 Force V4 protocol \n "
" -5 Force V5 protocol \n "
" -6 Force V6 protocol \n "
# ifndef USE_MSRPC
" -i <IpVersion> Use IP protocol (4 or 6) \n "
# endif // USE_MSRPC
" -e Show some valid examples \n "
" -x Show valid Apps \n "
2016-06-06 10:36:00 +08:00
" -d no DNS names, use Netbios names (no effect if -w is used) \n "
" -V show version information and exit \n \n "
2015-11-29 17:30:52 +08:00
" Advanced options: \n \n "
" -a <AppGUID> Use custom Application GUID \n "
" -s <ActGUID> Use custom Activation Configuration GUID \n "
" -k <KmsGUID> Use custom KMS GUID \n "
" -c <ClientGUID> Use custom Client GUID. Default: Use random \n "
" -o <PreviousClientGUID> Use custom Prevoius Client GUID. Default: ZeroGUID \n "
2016-08-15 18:35:59 +08:00
" -K <ProtocolVersion> Use a specific (possibly invalid) protocol version \n "
2015-11-29 17:30:52 +08:00
" -w <Workstation> Use custom workstation name. Default: Use random \n "
" -r <RequiredClientCount> Fake required clients \n "
" -n <Requests> Fixed # of requests (Default: Enough to charge) \n "
" -m Pretend to be a virtual machine \n "
" -G <file> Get ePID/HwId data and write to <file>. 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 <LicenseStatus> Use specfic license status (0 <= T <= 6) \n "
" -g <BindingExpiration> 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 "
" <port>: \t \t TCP port name of the KMS to use. Default 1688. \n "
" <host>: \t \t host name of the KMS to use. Default 127.0.0.1 \n "
# ifndef NO_DNS
" .<domain>: \t find KMS server in <domain> via DNS \n "
# endif // NO_DNS
" <app>: \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 + + )
{
2016-10-08 13:35:48 +08:00
uint_fast8_t len = ( uint_fast8_t ) strlen ( currentProduct - > name ) ;
2015-11-29 17:30:52 +08:00
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 (
" \n Request 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 ) ;
}
2016-08-15 18:35:59 +08:00
static void parseProtocolVersion ( void )
{
char * endptr_major , * endptr_minor , * period = strchr ( optarg , ( int ) ' . ' ) ;
if ( ! period )
{
errorout ( " Fatal: Protocol version must be in the format #.# \n " ) ;
exit ( ! 0 ) ;
}
long major = strtol ( optarg , & endptr_major , 10 ) ;
long minor = strtol ( period + 1 , & endptr_minor , 10 ) ;
if ( ( * endptr_major & & * endptr_major ! = ' . ' ) | | * endptr_minor | | * optarg = = ' . ' | | ! period [ 1 ] )
{
errorout ( " Fatal: Protocol version must be in the format #.# \n " ) ;
exit ( ! 0 ) ;
}
if ( major < 0 | | major > 0xffff | | minor < 0 | | minor > 0xffff )
{
errorout ( " Fatal: Major and minor protocol version number must be between 0 and 65535 \n " ) ;
exit ( ! 0 ) ;
}
ActiveLicensePack . kmsVersionMajor = ( int ) major ;
kmsVersionMinor = ( int_fast16_t ) minor ;
}
2015-11-29 17:30:52 +08:00
# 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
}
2016-08-15 18:35:59 +08:00
static const char * const client_optstring = " +N:B:i:l:a:s:k:c:w:r:n:t:g:G:o:K:pPTv456mexdV " ;
2015-11-29 17:30:52 +08:00
//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 ' :
2016-10-08 13:35:48 +08:00
switch ( getOptionArgumentInt ( ( char ) o , 4 , 6 ) )
2015-11-29 17:30:52 +08:00
{
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 ;
2016-10-08 13:35:48 +08:00
FixedRequests = getOptionArgumentInt ( ( char ) o , 1 , INT_MAX ) ;
2015-11-29 17:30:52 +08:00
break ;
case ' r ' : // Fake minimum required client count
incompatibleOptions | = VLMCS_OPTION_NO_GRAB_INI ;
2016-10-08 13:35:48 +08:00
ActiveLicensePack . N_Policy = getOptionArgumentInt ( ( char ) o , 0 , INT_MAX ) ;
2015-11-29 17:30:52 +08:00
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)
2016-10-08 13:35:48 +08:00
BindingExpiration = getOptionArgumentInt ( ( char ) o , 0 , INT_MAX ) ;
2015-11-29 17:30:52 +08:00
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 ;
2016-08-15 18:35:59 +08:00
kmsVersionMinor = 0 ;
break ;
case ' K ' : // Use specific protocol (may be invalid)
parseProtocolVersion ( ) ;
2015-11-29 17:30:52 +08:00
break ;
case ' d ' : // Don't use DNS names
dnsnames = FALSE ;
break ;
2016-06-06 10:36:00 +08:00
# ifndef NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
case ' v ' : // Be verbose
verbose = TRUE ;
break ;
2016-06-06 10:36:00 +08:00
# endif // NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
case ' m ' : // Pretend to be a virtual machine
VMInfo = TRUE ;
break ;
case ' w ' : // WorkstationName (max. 63 chars)
WorkstationName = optarg ;
if ( strlen ( WorkstationName ) > 63 )
{
2016-08-15 18:35:59 +08:00
errorout ( " \007 WARNING! Truncating workstation name to 63 characters (%s). \n " , WorkstationName ) ;
2015-11-29 17:30:52 +08:00
}
break ;
case ' t ' :
2016-10-08 13:35:48 +08:00
LicenseStatus = getOptionArgumentInt ( ( char ) o , 0 , 0x7fffffff ) ;
2016-08-15 18:35:59 +08:00
if ( ( unsigned int ) LicenseStatus > 6 ) errorout ( " Warning: Correct license status is 0 <= license status <= 6. \n " ) ;
2015-11-29 17:30:52 +08:00
break ;
# ifndef USE_MSRPC
case ' T ' :
ReconnectForEachRequest = TRUE ;
break ;
# endif // USE_MSRPC
case ' l ' :
incompatibleOptions | = VLMCS_OPTION_NO_GRAB_INI ;
break ;
2016-06-06 10:36:00 +08:00
# 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
2015-11-29 17:30:52 +08:00
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 ( " \n WARNING: Server's RPC protocol does not support NDR32. \n " ) ;
if ( UseRpcBTFN & & UseRpcNDR64 & & RpcFlags . HasNDR64 & & ! RpcFlags . HasBTFN )
errorout ( " \n WARNING: Server's RPC protocol has NDR64 but no BTFN. \n " ) ;
2016-06-06 10:36:00 +08:00
# ifndef NO_BASIC_PRODUCT_LIST
2015-11-29 17:30:52 +08:00
if ( ! IsEqualGuidLEHE ( & request - > KMSID , & ProductList [ 15 ] . guid ) & & UseRpcBTFN & & ! RpcFlags . HasBTFN )
errorout ( " \n WARNING: A server with pre-Vista RPC activated a product other than Office 2010. \n " ) ;
2016-06-06 10:36:00 +08:00
# endif // NO_BASIC_PRODUCT_LIST
2015-11-29 17:30:52 +08:00
}
# endif // USE_MSRPC
static void displayResponse ( const RESPONSE_RESULT result , const REQUEST * request , RESPONSE * response , BYTE * hwid )
{
fflush ( stdout ) ;
if ( ! result . RpcOK ) errorout ( " \n \007 ERROR: Non-Zero RPC result code. \n " ) ;
if ( ! result . DecryptSuccess ) errorout ( " \n \007 ERROR: Decryption of V5/V6 response failed. \n " ) ;
if ( ! result . IVsOK ) errorout ( " \n \007 ERROR: AES CBC initialization vectors (IVs) of request and response do not match. \n " ) ;
if ( ! result . PidLengthOK ) errorout ( " \n \007 ERROR: The length of the PID is not valid. \n " ) ;
if ( ! result . HashOK ) errorout ( " \n \007 ERROR: Computed hash does not match hash in response. \n " ) ;
if ( ! result . ClientMachineIDOK ) errorout ( " \n \007 ERROR: Client machine GUIDs of request and response do not match. \n " ) ;
if ( ! result . TimeStampOK ) errorout ( " \n \007 ERROR: Time stamps of request and response do not match. \n " ) ;
if ( ! result . VersionOK ) errorout ( " \n \007 ERROR: Protocol versions of request and response do not match. \n " ) ;
if ( ! result . HmacSha256OK ) errorout ( " \n \007 ERROR: Keyed-Hash Message Authentication Code (HMAC) is incorrect. \n " ) ;
2016-08-15 18:35:59 +08:00
if ( ! result . IVnotSuspicious ) errorout ( " \n WARNING: The KMS server is an emulator because the response uses an IV following KMSv5 rules in KMSv6 protocol. \n " ) ;
2015-11-29 17:30:52 +08:00
if ( result . effectiveResponseSize ! = result . correctResponseSize )
{
errorout ( " \n \007 WARNING: 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
2016-06-06 10:36:00 +08:00
# ifndef NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
if ( ! verbose )
2016-06-06 10:36:00 +08:00
# endif // NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
{
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 " ) ;
}
2016-06-06 10:36:00 +08:00
# ifndef NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
else
{
printf (
" \n \n Response 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 " ) ;
}
2016-06-06 10:36:00 +08:00
# endif // NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
}
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 ( " \n Performing 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 ) ;
2016-06-06 10:36:00 +08:00
# ifndef NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
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;
}
2016-06-06 10:36:00 +08:00
# endif // NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
}
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 ;
2016-06-06 10:36:00 +08:00
# ifndef NO_VERBOSE_LOG
if ( verbose ) printf ( " \n Performing RPC bind ... \n " ) ;
2015-11-29 17:30:52 +08:00
if ( rpcBindClient ( * s , verbose ) )
2016-06-06 10:36:00 +08:00
# else
if ( rpcBindClient ( * s , FALSE ) )
# endif
2015-11-29 17:30:52 +08:00
{
errorout ( " Warning: Could not bind RPC \n " ) ;
continue ;
}
2016-06-06 10:36:00 +08:00
# ifndef NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
if ( verbose ) printf ( " ... successful \n " ) ;
2016-06-06 10:36:00 +08:00
# endif
2015-11-29 17:30:52 +08:00
return ;
}
errorout ( " Fatal: Could not connect to any KMS server \n " ) ;
exit ( ! 0 ) ;
# endif // DNS
}
2016-08-15 18:35:59 +08:00
# endif // IS_LIBRARY
2015-11-29 17:30:52 +08:00
2016-08-15 18:35:59 +08:00
int SendActivationRequest ( const RpcCtx sock , RESPONSE * baseResponse , REQUEST * baseRequest , RESPONSE_RESULT * result , BYTE * const hwid )
2015-11-29 17:30:52 +08:00
{
size_t requestSize , responseSize ;
BYTE * request , * response ;
int status ;
result - > mask = 0 ;
2016-08-15 18:35:59 +08:00
if ( LE16 ( baseRequest - > MajorVer ) < 5 )
2015-11-29 17:30:52 +08:00
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 ;
2016-10-08 13:35:48 +08:00
* result = DecryptResponseV4 ( & response_v4 , ( const int ) responseSize , response , request ) ;
2015-11-29 17:30:52 +08:00
memcpy ( baseResponse , & response_v4 . ResponseBase , sizeof ( RESPONSE ) ) ;
}
else
{
RESPONSE_V6 response_v6 ;
2016-10-08 13:35:48 +08:00
* result = DecryptResponseV6 ( & response_v6 , ( int ) responseSize , response , request , hwid ) ;
2015-11-29 17:30:52 +08:00
memcpy ( baseResponse , & response_v6 . ResponseBase , sizeof ( RESPONSE ) ) ;
}
result - > RpcOK = TRUE ;
}
if ( response ) free ( response ) ;
free ( request ) ;
return status ;
}
2016-08-15 18:35:59 +08:00
# ifndef IS_LIBRARY
2015-11-29 17:30:52 +08:00
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 ( " \n Warning: 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 ( " \n Error 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 ) ) ;
2016-10-08 13:35:48 +08:00
vlmcsd_unlink ( fname ) ;
2015-11-29 17:30:52 +08:00
exit ( ! 0 ) ;
}
}
static void updateIniFile ( iniFileEpidLines * const restrict lines )
{
int_fast8_t lineWritten [ _countof ( * lines ) ] ;
2016-10-08 13:35:48 +08:00
# if !_MSC_VER
2015-11-29 17:30:52 +08:00
struct stat statbuf ;
2016-10-08 13:35:48 +08:00
# endif
2015-11-29 17:30:52 +08:00
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 , " ~ " ) ;
2016-10-08 13:35:48 +08:00
# if _MSC_VER
if ( ! PathFileExists ( fn_ini_client ) )
{
iniFileExistedBefore = FALSE ;
newIniBackupFile ( fn_bak ) ;
}
# else
2015-11-29 17:30:52 +08:00
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 ) ;
}
}
2016-10-08 13:35:48 +08:00
# endif
2015-11-29 17:30:52 +08:00
else
{
2016-10-08 13:35:48 +08:00
vlmcsd_unlink ( fn_bak ) ; // Required for Windows. Most Unix systems don't need it.
2015-11-29 17:30:52 +08:00
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 + + )
{
2016-09-04 22:03:54 +08:00
if ( * ( * lines ) [ i ] & & ! strncasecmp ( sourceLine , ( * lines ) [ i ] , strlen ( ePidGroup [ i ] ) ) )
2015-11-29 17:30:52 +08:00
{
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 ) ;
}
2016-10-08 13:35:48 +08:00
if ( ! iniFileExistedBefore ) vlmcsd_unlink ( fn_bak ) ;
2015-11-29 17:30:52 +08:00
free ( fn_bak ) ;
}
2016-10-08 13:35:48 +08:00
2015-11-29 17:30:52 +08:00
static void grabServerData ( )
{
RpcCtx s = INVALID_RPCCTX ;
WORD MajorVer = 6 ;
iniFileEpidLines lines ;
2016-09-04 22:03:54 +08:00
static int_fast8_t Licenses [ _countof ( lines ) ] = { 0 , 16 , 17 , 19 } ;
2015-11-29 17:30:52 +08:00
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 ;
}
2016-09-04 22:03:54 +08:00
printf ( " %i of %i " , ( int ) ( i + 7 - MajorVer ) , ( int ) ( 10 - MajorVer ) ) ;
2015-11-29 17:30:52 +08:00
displayResponse ( result , & request , & response , hwid ) ;
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 ) ;
}
2016-10-08 13:35:48 +08:00
vlmcsd_snprintf ( lines [ i ] , sizeof ( lines [ 0 ] ) , " %s = %s " , ePidGroup [ i ] , ePID ) ;
2015-11-29 17:30:52 +08:00
if ( response . MajorVer > 5 )
{
len = strlen ( lines [ i ] ) ;
2016-10-08 13:35:48 +08:00
vlmcsd_snprintf ( lines [ i ] + len , sizeof ( lines [ 0 ] ) - len , " / %02X %02X %02X %02X %02X %02X %02X %02X " , hwid [ 0 ] , hwid [ 1 ] , hwid [ 2 ] , hwid [ 3 ] , hwid [ 4 ] , hwid [ 5 ] , hwid [ 6 ] , hwid [ 7 ] ) ;
2015-11-29 17:30:52 +08:00
}
len = strlen ( lines [ i ] ) ;
2016-10-08 13:35:48 +08:00
vlmcsd_snprintf ( lines [ i ] + len , sizeof ( lines [ 0 ] ) - len , " \n " ) ;
2015-11-29 17:30:52 +08:00
}
if ( strcmp ( fn_ini_client , " - " ) )
{
updateIniFile ( & lines ) ;
}
else
{
printf ( " \n " ) ;
for ( i = 0 ; i < _countof ( lines ) ; i + + ) printf ( " %s " , lines [ i ] ) ;
}
}
2016-10-08 13:35:48 +08:00
int client_main ( int argc , CARGV argv )
2015-11-29 17:30:52 +08:00
{
# 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 ;
2016-08-15 18:35:59 +08:00
for ( requests = 0 , RequestsToGo = ActiveLicensePack . N_Policy = = 1 ? 1 : ActiveLicensePack . N_Policy - 1 ; RequestsToGo ; requests + + )
2015-11-29 17:30:52 +08:00
{
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 ( " \n The 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 ) ;
2016-10-08 13:35:48 +08:00
len = ( int ) utf8_to_ucs2 ( Request - > WorkstationName , ClientDnsNames . first [ index ] , WORKSTATION_NAME_BUFFER , WORKSTATION_NAME_BUFFER * 3 ) ;
2015-11-29 17:30:52 +08:00
index = rand ( ) % _countof ( ClientDnsNames . second ) ;
2016-10-08 13:35:48 +08:00
len2 = ( int ) utf8_to_ucs2 ( Request - > WorkstationName + len , ClientDnsNames . second [ index ] , WORKSTATION_NAME_BUFFER , WORKSTATION_NAME_BUFFER * 3 ) ;
2015-11-29 17:30:52 +08:00
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 ;
}
2016-06-06 10:36:00 +08:00
# ifndef NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
if ( verbose )
{
printf ( " \n Request Parameters \n ================== \n \n " ) ;
logRequestVerbose ( Request , & printf ) ;
printf ( " \n " ) ;
}
2016-06-06 10:36:00 +08:00
# endif // NO_VERBOSE_LOG
2015-11-29 17:30:52 +08:00
}
2016-08-15 18:35:59 +08:00
# endif // IS_LIBRARY